The Art of Code generation with Cline (Claude + OpenAI)

Code assistants like Claude-Dev and Copilot are very useful and can save a lot of time. However, they have various pitfalls that can waste resources and affect quality and costs. While I've discussed these issues in previous posts, this blog entry will summarize the most common challenges and offer best practices for even better results.

If you're not familiar with Claude-Dev (now Cline), it might be worth checking out. In short, it is an incredibly powerful open-source code assistant that works with any LLM capable of reasoning and code generation.

1. Start with Architecture, Not Code!

Before diving into coding, use AI to generate architecture documentation and diagrams. This ensures a clear and scalable structure from the outset.

Example Prompt:

Create a Mermaid sequence diagram for a user registration process in a web app.

Generated Diagram:

User->>Web App: Fill Registration Form
Web App->>Server: Submit Registration Data
Server->>Database: Store User Data
Database-->>Server: Confirmation
Server->>User: Registration Successful Message

I discussed this approach in an earlier post, which you can read here:

Architecture-driven code generation with Claude --- a complete tutorial

2. Build Features Incrementally!

Add one feature at a time, updating your architecture diagrams before implementation. This prevents overwhelming the AI and ensures each feature is fully functional before moving on. Incremental development allows you to save intermediate working results, so if something goes wrong, you don't have to start over. It also leverages Claude-Dev's cache efficiently, saving on costs.

Example Workflow:

  1. Implement User Registration:
  • Prompt Claude-Dev to create the user registration feature.
  • Commit the changes to version control.
  • Test thoroughly to ensure it's working.
  1. Add Email Verification:
  • Update the architecture diagram to include email verification.
  • Prompt Claude-Dev to implement the email verification feature.
  • Commit and test again.

Example Prompt:

"Update the previous diagram and code to include email verification after user registration."

You can find some more examples in an earlier post with a real-world example.

From Idea to Working App with Claude Dev and GPT-4 (Part II)

3. Keep It Modular!

Encourage the AI to generate modular code. Modular code is easier to maintain, debug, and update. Claude-Dev can sometimes create monolithic files; emphasizing modularity helps prevent this.

Example Prompt:

"Generate a modular folder structure for a React Todo app, separating components, services, and utilities."

Folder Structure:

/src
/components
/TodoList.jsx
/TodoItem.jsx
/services
/api.js
/utilities
/helpers.js

In real-world applications, you may have a wonderful structure on day one, but the code does not grow linearly across all files, some files may become monolithic and ugly. If you notice this growth (e.g. a large number of LOC), you can simply ask Claude-dev to refactor the code and split it into files.

 If you work often with Claude-dev, refactoring code into smaller chunks will save you a lot of money and time.

Here is an example where I simply ask Claude-Dev to split a monolithic class chatinterface and as you can see it splits it into several files.
Then when I need to modify something, he will only read and edit the relevant files, saving you a lot of money and time waiting for Claude to read and write unrelated code.

4. Commit Early, Commit Often!

Use version control carefully. Commit after every feature or significant change to ensure that you can easily roll back if necessary. This is crucial because Claude-Dev can sometimes generate code that introduces problems; frequent commits allow you to revert to a working state.

Example Commands:

git add .
git commit -m "Implement user registration feature"
git push origin main

If, between two commits, you have accepted some changes that break the code, it can be difficult for Claude to know what he broke, especially if you have already progressed with the code generation.
The best solution is to get the git diff, give it to Claude, and ask him to fix it, regardless of Claude's current context.

Here is a sample prompt:

You screwed up the search feature between these two commits.
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 92e740e..41357aa 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -4,7 +4,6 @@ import { useState, useEffect } from 'react';
import { useSession, signIn, signOut } from 'next-auth/react';
....

Another common problem is that when the conversation gets too long, Claude and other models tend to produce placeholders instead of the actual code. If you are not careful when producing code, you may end up losing functionality instead of adding or modifying existing functionality. In this case I strongly recommend to reset the conversion and start a new session, your chance to get a complete code is probably higher.

An alternative more favourable approach, if the placeholders are just old, is simply to manually copy the code from the original file to the same location in the file being edited and save it. Claude-Dev will take your changes and in this case will not remove the original code and replace it with silly placeholders.

4. Choose Your Model Wisely!

Pay attention to the AI model you're using. Different tasks may require different models for optimal performance. The default Claude-sonnet 3.5 model is recommended for reasoning tasks, as it is the most suitable and reliable. Other models offered by Claude-Dev may not perform as well in complex reasoning scenarios due to their lack of planning capabilities compared to Sonnet.

Example Prompt:

generate unit tests for the login function.

Notes:

  • While Claude-Dev supports multiple models, experience shows that claude-sonnet 3.5 provides the best results for most coding tasks.
  • Be cautious, as Claude-Dev may sometimes replace models without explicit notification. Always verify that the code is using the intended model to avoid unintended costs or performance issues.

5. Watch Your Token Count!

Keep an eye on costs, especially when generating large amounts of code. Utilize Claude-Dev's token tracking and cost analysis features to stay within budget.

How to Monitor Tokens:

  • In Claude-Dev: Token counts and costs can be viewed in the Claude summary at the top of the page.
  • Cost Analysis Tools: Use the built-in tools within Claude-Dev for detailed cost analysis.

Important Notes:

  • When using Claude-Dev through other deployments like AWS Bedrock, caching might not be available as of today. This could increase costs significantly since the cache reduces token usage by up to 90% in Claude-Dev.
  • Only when using Claude-Dev directly through claude.ai do you have access to caching features.
  • Avoid using cache-unfriendly prompts or initiating new tasks unnecessarily, as this can reset the cache and increase costs.

We discussed Claude caching in more detail in an earlier post.

Is Prompt Caching the New RAG?

6. Test Thoroughly!

Always test generated code. AI can make mistakes, and thorough testing ensures reliability. Claude-Dev may generate code that doesn't work as expected; catching problems early saves time.

Example Prompt:

Generate unit tests for the user registration function using Jest.

7. Write Clear Prompts!

The clearer your prompt, the better the code you'll get. Avoid ambiguity to get accurate results. Claude-Dev sometimes tries to rationalise changes it thinks are safe to make; explicit instructions help prevent unintended changes.

Example:

  • Ambiguous Prompt:  Create a login function.
  • Clear Prompt: Create a login function in Node.js that authenticates users using JWTs. Do not modify other existing functions.

Tip:

  • Add Don't change anything else" at the end of your prompts to ensure only the intended parts are modified.
  • Be specific about the technologies, libraries, and frameworks you want to use.

8. Think Security First!

Always review generated code for security implications. Ensure that no sensitive data is exposed and that best security practices are followed. Claude-Dev might sometimes generate client-side code that should be server-side for security reasons.
If you don't explicitly tell the LLM to follow best practices, it may make changes that are quick and dirty, resulting in a mess and vulnerabilities in the generated code.

Example Prompt:

"Verify that API keys are not exposed on the client side and are securely stored on the server."

Common Security Mistake:

  • Exposing API Keys: Including API keys in client-side code or in public repositories.

Solution:

  • Use environment variables stored in a .env file that is not checked into version control.
  • Ensure API calls that require sensitive information are made from the server side, not the client side.

9. Set Up Your Environment Properly!

Make sure that all necessary libraries and environment variables are set up correctly to avoid runtime errors and streamline development. Claude-Dev may not automatically set up the environment and install the required libraries.

10. Review, Understand, Then Implement!

Always review and understand the generated code before implementing it. This ensures that you can spot potential problems and maintain control over your code base. Claude-Dev may sometimes make changes that don't match your intentions.

Example Prompt:

"Explain how the authentication middleware works and identify any potential issues."

Understanding the Code:

  • Review each function and its purpose.
  • Check for security vulnerabilities or inefficient logic.
  • Ensure that the code aligns with your project's architecture and standards.

11. Manage Multiple Projects Carefully

Avoid having more than one project open in the same workspace. This can confuse Claude-Dev when you ask for changes, as it may apply them to the wrong project.

Tips:

  • Use separate workspaces or IDE windows (e.g., separate VSCode windows) for different projects.
  • Close unrelated projects before starting a new task with Claude-Dev.

Note:

  • Keeping only one project in your Claude-Dev workspace helps the AI focus on the correct codebase.

12. Simplify Complex Tasks

If Claude-Dev struggles with a complex task in a large project, try simplifying the problem or isolating it in a smaller, simpler context.

Example:

  • If a feature isn't working in your main project, create a simple HTML page or a minimal project to test the feature independently.

Benefit:

  • Helps identify whether the issue is with your code or with Claude-Dev's understanding.

13. Stay Updated on Model Names and Capabilities

Ensure that the generated code uses the correct models (e.g. GPT-4, GPT-3.5-turbo) to avoid unintended costs or performance issues.

Tips:

  • Claude-Dev may not have the latest model names or API changes.
  • Verify that the code generated uses the intended models.
  • Be cautious, as Claude-Dev might sometimes replace models without explicit notification.

Example Prompt:

"Ensure the code uses 'gpt-3.5-turbo' model for OpenAI API requests, not 'gpt-4'."

14. Encourage Continuous Learning

Help Claude-Dev learn from his mistakes and improve over time by instructing him to create "Lessons Learned" documents when problems occur.

Example Prompt:

"Whenever there are more than 2 errors in a task you are working on and it finally works, automatically save the result to a file named 'lessons_learned.md' without me explicitly asking for it."

Benefit:

  • Claude-Dev can refer to this document in future tasks to avoid repeating the same mistakes.
  • Improves efficiency and code quality over time.

I discussed this approach in an earlier post, which you can read here

Iterative Refinement: How ChatGPT Enhances Its Own Content Through Self-Review

15. Debug logging helps

You will often come across code that does not work as expected without causing errors. This can be a tedious task to explain if you need Claude to help you fix the code.
The code might not work as expected. If you need Claude to fix it, let him generate traces and logs in the area you need help with, run the application with tlogs, and then pass him the logs. This way, you can see how the application behaves from a data flow standpoint.

And if nothing works, try this:

Sometimes Claude is just not able to deal with a particular problem properly. This can happen with complex problems, but also with incredibly simple problems where he goes round in circles.
What you can do in this case:

  1. Use a smarter model like OpenAI o1-mini and give it all the necessary information (code snippets), describe the problem and ask for advice. Then copy the result as is to Claude-Dev and let him fix it using the advice given. This has worked perfectly for me in many cases where Claude has got the hang of it and starts repeating himself.
  2. The second, or perhaps additional, solution is to let him write a test case with a very clearly specified case where it does not work, and let him fix the code in such a way that this case works. This is very helpful if you want to avoid a lot of iterations where Clude codes something that does not work and you do the manual test and go back and forth with him. Better to let them know exactly what you are testing, fix the code, and run the test (and retest) yourself. This can save you a lot of time.
  3. And of course, you can solve the problem yourself:)
    Here's an example where only a small thing needed to be fixed, the parameter "messages". Literally a change of 3 lines of code.

I gave this bug to OpenAI, o1-mini and Claude to fix. And the answer from o1-mini was surprisingly long and I am not sure if it would have even solved this small problem (I shortened it to more than 30% of the original answer). Solving it by a human is luckily still much faster:)

Conclusion:

Putting it all together:

By following these best practices, you'll be well-equipped to harness the full potential of Cline. These strategies enhance efficiency, code quality, and ensure cost-effective and scalable project development.

Happy coding😄