Agent Skills in Claude Code and Visual Studio Code: Setup, Benefits, Risks, and a Step-by-Step Example

Image
 AI coding assistants are useful for one-off questions, but many development tasks are not one-off tasks. A team may follow the same testing procedure before every release, use a specific format for code reviews, or require certain checks whenever a database migration is created. Repeating those requirements in every prompt is inefficient. Putting all of them into a permanent instruction file is not always ideal either, because the assistant may receive irrelevant information for tasks that do not need it. This is the problem that Agent Skills are designed to solve. A skill packages reusable instructions, supporting files, examples, and optional scripts into a folder. Claude Code or GitHub Copilot in Visual Studio Code can discover that folder and load its contents when the current task matches the skill’s purpose. Both environments support the open Agent Skills format, which makes it possible to share some skills across tools. This guide explains what skills are, how they differ ...

Why You Should Build Your App One Small Feature at a Time


AI coding tools make it tempting to ask for the entire application in one prompt.

You already have a project brief, a list of features, and a clear idea of the final result. It may seem efficient to give the whole document to Claude Code or GitHub Copilot and ask the tool to build everything at once.

That approach can produce a large amount of code quickly.

It can also produce a large amount of code that is difficult to understand, test, or repair.

A safer approach is to divide the application into small features that each create one visible result. You implement one feature, review the change, test it, commit it, and then move to the next feature.

This article explains how to break the Personal Reading List Tracker into manageable implementation steps.

What You Will Learn

By the end of this guide, you should be able to:

  • explain why large AI coding prompts create difficult reviews;
  • divide an application into small vertical features;
  • identify dependencies between features;
  • define one visible outcome for each task;
  • connect each prompt to one focused Git commit;
  • choose a practical implementation order;
  • distinguish project setup from user-facing behavior;
  • create a feature plan for the Personal Reading List Tracker;
  • decide when a feature is small enough to begin.

Why “Build the Whole App” Is a Weak First Task

Consider this prompt:

Build a complete personal reading list application with a responsive interface, form validation, status filtering, localStorage, editing, deletion, tests, and deployment configuration.

The request is understandable, but it contains many independent decisions.

The AI must decide:

  • which files to create;
  • how the HTML should be structured;
  • how the visual design should work;
  • how the book data should be modeled;
  • how validation should behave;
  • how books should be rendered;
  • how filters should interact with state;
  • how local storage should recover from invalid data;
  • how deletion should update storage;
  • which test approach to use;
  • which deployment service to target.

If the finished result contains a problem, identifying the source becomes difficult.

A filtering bug may come from:

  • the filter control;
  • the status values;
  • the rendering function;
  • the stored data;
  • the event handler;
  • the HTML markup.

A smaller task gives you fewer possible causes.

Large Prompts Create Large Diffs

An AI coding assistant may respond to one large prompt by changing:

index.html
styles.css
app.js
package.json
package-lock.json
README.md
test/app.test.js
deployment-config.json

That creates a wide Git diff.

You now need to review:

  • the page structure;
  • the styling;
  • the application logic;
  • new dependencies;
  • test configuration;
  • documentation;
  • deployment settings.

Even when every file is relevant to the final application, they may not belong in one review or commit.

A smaller task might change only:

index.html

For example:

Create the accessible HTML structure for the book form and empty list state.

That diff is much easier to inspect.

You can check:

  • whether labels match inputs;
  • whether status values match the brief;
  • whether the list container exists;
  • whether unnecessary scripts or packages were added.

The review has a clear focus.

Small Features Create Better Feedback Loops

A useful development loop is:

Choose one feature
→ Define expected behavior
→ Ask the AI
→ Review the diff
→ Test the result
→ Commit

Each cycle produces information.

You learn:

  • whether the project structure is working;
  • whether the AI understood the brief;
  • whether the selected approach is maintainable;
  • whether the feature needs adjustment;
  • whether the next task can build safely on the current state.

A large one-shot build delays this feedback until many decisions have already been made.

Small steps reveal problems earlier.

Build Vertical Slices, Not Random Pieces

A vertical slice is a small piece of functionality that produces a visible or testable result.

For example:

The user can submit a valid book title and see it appear in the list.

That slice may include a small amount of:

  • HTML;
  • JavaScript state;
  • event handling;
  • rendering.

It crosses more than one technical layer, but it creates one complete behavior.

A horizontal task focuses on one technical layer without necessarily creating a usable result.

For example:

Create every JavaScript utility function the application may need.

That may produce many functions before the interface is ready to use them.

For a beginner project, vertical slices are usually easier to verify because each one answers a user-facing question.

Examples include:

Can the user see the form?
Can the user add a valid book?
Can the user see an error for a blank title?
Can the user remove a book?
Can the list survive a page refresh?

Each question has a visible answer.

Start with the Simplest Working Path

The first implementation should prove the main workflow with as little complexity as possible.

For the reading list project, the main workflow is:

Enter book details
→ Submit the form
→ See the book in the list

You do not need filtering, storage, editing, or an API to prove this workflow.

A practical first version can store books only in memory.

That means the list disappears after a page refresh.

This is acceptable temporarily because persistence is a separate feature.

The first goal is not to complete the final product.

It is to prove that the user can add and view a book.

Identify Feature Dependencies

Some features depend on earlier features.

For example, you cannot meaningfully add status filtering before books can be rendered.

You also cannot test persistence before the application has data worth saving.

A dependency sequence might look like:

Page structure
→ Basic styling
→ In-memory book state
→ Add Book behavior
→ Rendering
→ Validation
→ Removal
→ Filtering
→ Local storage
→ Final polish

This sequence avoids building features against missing foundations.

Page Structure Comes First

The JavaScript needs:

  • a form;
  • inputs;
  • a status selector;
  • a list container;
  • an empty state.

Those elements should exist before event handlers depend on them.

Rendering Comes Before Filtering

Filtering changes which books are rendered.

The app therefore needs a reliable rendering function before filter logic is introduced.

Removal Comes Before Persistence or After It

Either order can work.

However, if removal is implemented before persistence, you can test the core behavior without storage complexity.

Then persistence can be connected to both addition and removal in one later feature.

Persistence Comes After Core Behavior

Local storage should preserve an already working application.

It should not be used to hide unclear state management.

Build the core behavior first, then persist it.

A Feature Plan for the Reading List Tracker

The Personal Reading List Tracker can be divided into the following implementation stages.

Feature 1: Create the Page Structure

Goal

Create the semantic HTML needed for the application.

Files

index.html

Expected Result

The page displays:

  • a heading;
  • a title input;
  • an optional author input;
  • a status selector;
  • an Add Book button;
  • a filter control;
  • an empty-state message;
  • a list container.

Not Included Yet

  • JavaScript behavior;
  • local storage;
  • responsive styling;
  • dynamic books.

Possible Commit

Create reading list page structure

Feature 2: Add Basic Styling

Goal

Make the existing interface readable and usable.

Files

styles.css

Expected Result

The page has:

  • a clear content width;
  • readable typography;
  • usable form spacing;
  • visible labels;
  • distinct buttons;
  • visible focus styles;
  • a layout that does not break on a narrow screen.

Not Included Yet

  • complex animations;
  • theme switching;
  • book-cover layouts;
  • visual redesign of unrelated elements.

Possible Commit

Add responsive base styles

Feature 3: Create the Initial Book State and Renderer

Goal

Define an in-memory books array and display its contents.

Files

app.js

Expected Result

The application can render a small sample list or an empty state.

Not Included Yet

  • form submission;
  • validation;
  • removal;
  • filtering;
  • persistence.

Possible Commit

Add book list rendering

Feature 4: Add Valid Books Through the Form

Goal

Allow the user to submit a book and see it in the list.

Files

app.js

The HTML may need a small correction only if a required selector or ID is missing.

Expected Result

A valid submission creates a book object with:

id
title
author
status
createdAt

The new book appears immediately.

Not Included Yet

  • detailed validation messages;
  • local storage;
  • filtering;
  • editing.

Possible Commit

Add books through the form

Feature 5: Validate Book Titles

Goal

Reject invalid titles without changing the list.

Expected Result

  • normal titles are accepted;
  • leading and trailing spaces are removed;
  • empty titles are rejected;
  • whitespace-only titles are rejected;
  • author remains optional;
  • successful submission clears the appropriate fields.

Possible Commit

Validate book titles

This feature is separate from basic form submission because validation introduces its own behavior and edge cases.

Feature 6: Remove a Book

Goal

Allow one selected book to be removed.

Expected Result

  • every rendered book has a remove action;
  • only the selected book is removed;
  • the list rerenders;
  • the empty state returns when the final book is removed.

Possible Commit

Add book removal

Feature 7: Filter by Reading Status

Goal

Show books matching the selected status.

Expected Result

The user can view:

  • all books;
  • Want to Read;
  • Reading;
  • Finished.

Filtering must not modify the underlying data.

Possible Commit

Filter books by reading status

Feature 8: Add Browser Persistence

Goal

Preserve the reading list across page refreshes.

Expected Result

  • books load from local storage;
  • additions are saved;
  • removals are saved;
  • missing data becomes an empty list;
  • invalid saved JSON does not permanently break the app.

Possible Commit

Persist books in local storage

Feature 9: Improve Empty and Error States

Goal

Make the interface explain what is happening.

Expected Result

  • an empty-state message appears when no books exist;
  • validation feedback is visible;
  • the feedback is removed when appropriate;
  • filtering with no matches produces a useful message.

Possible Commit

Improve empty and validation states

Feature 10: Final Responsive and Accessibility Review

Goal

Improve the finished interface without changing the application scope.

Expected Result

  • keyboard navigation works;
  • labels remain visible;
  • focus styles are clear;
  • narrow screens remain usable;
  • buttons have understandable names;
  • status information is readable.

Possible Commit

Improve accessibility and mobile layout

One Feature Should Produce One Main Outcome

A feature task is small enough when you can describe its outcome in one sentence.

Examples:

The user can add one valid book.
The user can remove one selected book.
The user can filter books by status.
The list remains after a page refresh.

A task may still require more than one file.

The goal is not “one file per feature.”

The goal is one coherent result per feature.

For example, adding validation may require:

  • JavaScript logic;
  • an HTML error-message element;
  • a small CSS rule.

Those changes still belong together because they produce one user-visible behavior.

Use Acceptance Criteria to Control Feature Size

Acceptance criteria help determine whether a feature is focused.

For “Remove a Book”:

- Every book has a remove action.
- Removing one book leaves the others unchanged.
- The list updates immediately.
- The empty state appears when no books remain.

That is a manageable feature.

Now compare it with:

- Remove books.
- Edit books.
- Undo removal.
- Restore deleted books after login.
- Synchronize deletion across devices.

The second set describes several different systems.

Split it.

A useful question is:

Can I verify this feature with one short test checklist?

If the checklist becomes long or includes unrelated workflows, the feature may be too large.

Connect Each Feature to One Prompt

A feature plan becomes useful when each feature maps to a focused AI request.

For example:

Feature:
Add book removal.

Prompt goal:
Add one remove action to each rendered book and update the in-memory books array when selected.

Allowed files:
app.js

Acceptance criteria:
- One selected book is removed.
- Other books remain.
- The empty state returns when needed.

Excluded:
- Editing
- Undo
- Local storage
- Confirmation dialog

This prompt is easier to reason about than:

Make the book cards fully interactive.

Connect Each Feature to One Git Commit

A useful feature usually creates a natural commit boundary.

For example:

Prompt:
Add status filtering.

Review:
Check filter values and rendering behavior.

Test:
Select each status and confirm the correct books appear.

Commit:
Filter books by reading status.

This relationship is valuable:

One feature
→ One focused prompt
→ One reviewable diff
→ One test checklist
→ One meaningful commit

Not every task must produce exactly one commit.

A complicated feature may need more than one.

The important point is that unrelated work should not be grouped together only because it occurred in the same AI session.

Stop After the Feature Works

Once the current feature meets its acceptance criteria, stop.

Do not immediately ask:

Now improve everything else.

Instead:

  1. Run git status.
  2. Review the diff.
  3. Test the feature.
  4. Commit the verified result.
  5. Update the task list.
  6. Begin a new prompt for the next feature.

This creates a stable checkpoint.

If the next feature fails, you still have a known working state.

Avoid Premature Refactoring

AI tools often notice opportunities to reorganize code.

After one or two features, the assistant may propose:

  • multiple modules;
  • a state-management layer;
  • reusable classes;
  • a component system;
  • utility directories;
  • a build tool.

Some refactoring may eventually be useful.

Early refactoring can create complexity before the project’s real patterns are visible.

For a small beginner app, a simple app.js file may be easier to understand than a six-folder architecture.

Refactor when there is a concrete reason, such as:

  • repeated logic;
  • an overly long function;
  • difficult testing;
  • unclear responsibilities;
  • a feature that cannot be added safely.

Do not refactor only because the AI prefers a more elaborate structure.

Handle Discoveries Without Expanding the Current Task

While building one feature, you may discover another issue.

For example, while adding removal, you may notice that duplicate book IDs are possible.

Do not automatically add a full ID-management system inside the same task.

Record the discovery:

Follow-up task:
Review ID generation and duplicate handling.

Then finish the current feature if it remains safe to do so.

This practice keeps the current diff focused.

It also prevents one problem from turning into a chain of unrelated changes.

Know When a Feature Is Too Small

Small tasks are useful, but a task can be divided so far that the workflow becomes inefficient.

For example:

Task 1: Add opening form tag.
Task 2: Add closing form tag.
Task 3: Add title label.
Task 4: Add title input.

These steps belong to one coherent page-structure feature.

A useful feature should create a meaningful result.

The page structure feature can include all required form controls because they are reviewed together and do not introduce complex behavior.

The goal is not the smallest possible change.

It is the smallest useful and reviewable change.

A Practical Feature-Sizing Test

Before sending a prompt, ask:

  • Can I describe the outcome in one sentence?
  • Does it serve one user need?
  • Can I list the expected files?
  • Can I test it in a few steps?
  • Can I review the diff without losing track of the goal?
  • Can the result become a meaningful commit?
  • Can I exclude unrelated features clearly?
  • Can I return to the previous checkpoint if it fails?

When most answers are yes, the feature is probably small enough.

Example: Breaking Down Local Storage

“Add local storage” may still be too broad if the current application is unstable.

Break the work into a sequence.

Step 1: Save After Add

When a valid book is added, save the current books array under one storage key.

Step 2: Load at Startup

When the page loads, read the saved array and render it.

Step 3: Save After Removal

After removing a book, update the stored array.

Step 4: Handle Invalid Data

If the saved value contains invalid JSON, recover with an empty list and show a concise warning in the console.

These may be separate prompts or one focused persistence feature, depending on the size of the current codebase.

The decision should be based on reviewability.

Practical Advice from AI-Assisted Development

In real projects, small changes are easier to review because the reviewer can keep the intended behavior in mind while reading the diff.

That principle becomes even more important with AI-generated code.

An AI assistant may produce correct-looking code very quickly, but the human review speed does not increase at the same rate.

Keeping each task small balances that difference.

When I review an AI-assisted change, I want to understand:

  • what the task intended;
  • which files changed;
  • why each change was necessary;
  • how the result was verified.

A large mixed-purpose change makes those questions harder to answer.

Incremental development is therefore not only a beginner technique. It is a practical risk-control method.

The Recommended Build Order

For the Personal Reading List Tracker, use this sequence:

1. Create the page structure.
2. Add basic responsive styling.
3. Create book state and rendering.
4. Add valid books through the form.
5. Validate titles.
6. Remove books.
7. Filter by status.
8. Add local storage.
9. Improve empty and error states.
10. Review accessibility and mobile behavior.
11. Add tests where appropriate.
12. Prepare deployment.

Each step should begin from a clean or understood Git state.

Each completed step should end with:

git status
git diff

Then test, stage, review, and commit.

Verify Your Feature Plan

Before beginning implementation, confirm that your plan:

  • starts with the main user workflow;
  • places dependent features in the correct order;
  • avoids adding a backend too early;
  • separates local storage from basic form behavior;
  • separates filtering from rendering;
  • gives each feature a visible result;
  • includes acceptance criteria;
  • creates useful Git commit boundaries;
  • leaves optional ideas for later;
  • keeps the first version aligned with the project brief.

The reading list project now has a practical path from an empty repository to a working application.

Conclusion

Building one small feature at a time makes vibe coding easier to control.

Small tasks produce clearer prompts, smaller Git diffs, more focused tests, and safer commits. They also make it easier to identify which change introduced a bug and return to a known working state.

For the Personal Reading List Tracker, we will not ask the AI to build the complete application in one step.

We will move through page structure, styling, rendering, form behavior, validation, removal, filtering, persistence, and final review as separate features.

The next article will focus on reviewing AI-generated code even when you are not an expert in the language. We will use file scope, behavior, naming, dependencies, error handling, Git diffs, and testing to decide whether a generated change is safe to keep.

Comments

Popular posts from this blog

Claude Code Multi-Agent Setup for Beginners: Models, Roles, and Your First Project

The Limits and Future of Vibe Coding

How to Test and Deploy Your First Vibe-Coded App