DEV Community

ujjavala
ujjavala

Posted on

A week with Claude Code: lessons, surprises and smarter workflows

Exploring Claude Code After Copilot and Cursor

I’ve spent quite some time experimenting with different AI coding assistants. GitHub Copilot and Cursor have been my primary tools in the past. Copilot is great for inline completions but still struggles with deeper code context. Cursor can understand the entire project context and is a powerful coding companion.

I got access to Claude Code and decided to put it through its paces. It integrates with shell commands, scripts, and workflows that don’t rely on a full-blown GUI. My goal? To understand how well it can work with complex environments. Can it become a serious part of my daily workflow?

Working Across Modern and Legacy Repos

We build in a Turbo + Next.js monorepo. Everything lives together: multiple deployable apps, shared packages, infrastructure code, and common tooling. The monorepo is powerful but complex. On top of that, we maintain a couple of legacy repos with older frameworks and patterns. I wanted to find out how much Claude Code could assist with both modern and legacy setups. I also needed to know what files and context were necessary for it to work reliably.

From Skepticism to Smooth Experience

When I first started using Claude Code, I didn’t expect much. Was it just another tool in the mix? Would it fit into my workflow naturally? The first day was tough. It misunderstood unclear instructions. It created overly complex mocks and sometimes suggested edits in the wrong folders. But by the middle of the week, things began to click. When I shared my needs—file paths, inputs, outputs, and constraints—Claude provided clean code, clear explanations, and helpful scaffolding for the repo. It felt like having an assistant who really understood the monorepo. I saw it as a teammate, not just a generator.

When Claude Code Gets It Right… and When It Doesn’t

Claude Code shines when I’m clear about what I want. It produces clean code and good explanations. However, when I’m vague, it can over-engineer, add unnecessary details, or suggest layers that aren’t needed.

For instance, it suggested reducing the number of files in a design system. This went against our guidelines, which emphasise separation of concerns. In another case, it had issues with CDK for Terraform for Datadog monitoring. It often needed reminders that cdktf is behind the UI version. The same problem came up with Git workflows: I now use Claude to generate commit messages and draft PRs consistently. Still, I sometimes prefer to make a few commits manually. It occasionally forgets to follow templates or the CLAUDE.md context.

Standardising prompts and preserving context in local Claude Code files improves output reliability. Over time, as Claude Code gets more MCP integrations and workflow context, , it can manage routine PR and commit tasks swiftly. This change allows developers to focus on details and think critically about changes. Takeaway: think first, provide focused context, and then ask for precise changes to get safe, predictable results.

The Token Constraint Problem

Another big limitation: token limits and cost. Claude Code gets expensive quickly if you keep adding large context files. Cursor avoids this pain by indexing the entire repo locally, so there’s no token burn at all. Claude Code? You’re constantly balancing context quality with token usage.

MCP Integrations: Making Claude Code Work Across Tools

I tested connecting Claude Code directly to our MCPs—Jira, GitHub, and others—to see how it could improve our workflows. Claude Code can automatically get ticket details in Jira. It can create branches, plan changes, and update testing notes. On GitHub, it created draft PRs with all branch commits. It used our templates, added checklists, and linked tickets correctly.

The results were clear: fewer context switches, faster PR creation, and consistent team conventions. Some routine git tasks seemed quicker by hand at first, but full integration made complex workflows safer and faster over time. MCP connections changed Claude Code from a helper to a dependable workflow partner. Now, it links code, tickets, and design while also respecting legacy constraints.

The Secret Weapon: CLAUDE.md

The key to Claude’s usefulness is CLAUDE.md. It’s not just a readme; it’s a complete, structured knowledge base that gives Claude Code everything it needs to operate safely. Without it, the AI overlooks key details. These include folder structures, package boundaries, team ownership, workflows, naming conventions, and legacy patterns. With it, Claude Code acts like a team member. If I didn’t provide the exact file or related configs, it made wrong assumptions or left gaps in the solution. Unlike Cursor, which absorbs the full repo and “just knows,” Claude Code needed manual context every time. This slowed down fixes and made iterative edits harder in a large monorepo.

Here is where claude init helps: it bootstraps the CLAUDE.md for a repo, but the file must still be carefully curated and expanded over time. A good CLAUDE.md isn’t just documentation; it’s a memory anchor. It should have key sections, numbering, and # headers that Claude Code can latch onto and reliably “memorise” across sessions.

CLAUDE.md Sections in Detail

1. Quick Command Reference

This is how I tell Claude Code how to run common tasks.

Example snippet from my CLAUDE.md file:

claude story: Automatically generates a structured story with acceptance criteria.claude pr: Creates a PR template pre-filled with ticket links, checklists, and review requirements.claude commit: Formats commits with ticket naming conventions and validates pre-commit checks.claude dev: Guides the full workflow from ticket assignment to deployment.claude quick: Gives frequently used monorepo commands for setup, testing, and building.claude fix: Suggests solutions to common errors or broken workflows.

These shortcuts reduce context switching. I could ask Claude Code to generate a story, scaffold a PR, or suggest the next CLI command in a sequence without explaining conventions every time.

Let’s go through a couple of examples to understand this better.

claude commit:

Scenario: You're on the branch feature/XYZ-123-user-profile-photo-upload. You've added image upload functionality. Here’s what you updated in your CLAUDE.md file:

### claude commit\- Automatically formats commits as "XYZ-123: description"- Runs pre-commit checks (lint, tests)- Includes Claude co-author attribution

What claude commit does:

  1. Extracts ticket number from branch name: XYZ-123
  2. Analyzes staged changes to understand what was modified
  3. Runs pre-commit checks (lint, tests)
  4. Generates commit message in XYZ format
  5. Includes Claude co-author attribution
# Commandclaude commit# Generated commit messageXYZ-123: implement user profile photo upload with validation🤖 Generated with Claude CodeCo-Authored-By: Claude <noreply@anthropic.com>

What it automatically handles:

  1. Stages all unstaged changes (follows the "always add all files" rule)
  2. Checks for any remaining unstaged changes before committing
  3. Runs pnpm lint and pnpm test as pre-commit checks
  4. Uses proper XYZ-123 format extracted from branch name
  5. Writes descriptive commit message based on file changes
  6. Adds Claude attribution

Manual equivalent would be:

git add .pnpm lintpnpm testgit commit -m "XYZ-123: implement user profile photo upload with validation

The claude commit automates the whole workflow. It also keeps things consistent with XYZ team conventions.

claude story:

Scenario: Create a user story for ticket XYZ-189 about adding two-factor authentication.

In my CLAUDE.md file, I have something along the lines of the following:

**Template Output**:"As a [stakeholder], I want to [action] so that [benefit]."**Acceptance Criteria:**- [ ] Functional requirement 1- [ ] UI/UX expectation - [ ] Data requirement- [ ] Performance consideration- [ ] Edge case handling- [ ] Error handling- [ ] Testing requirement**Jira Details:**- Project: XYZ- Story Points: [estimate]- Labels: [feature1, feature2, etc.]- Dependencies: [Team1-XXX, Team2-XXX if applicable]

What claude story does:

  1. Analyzes codebase patterns
  2. Generates user story in XYZ team format
  3. Creates acceptance criteria
  4. Adds Definition of Done
claude story XYZ-189

And generates something like:

XYZ-189: Two-Factor Authentication for User AccountsUser StoryAs a user administrator, I want to enable two-factor authentication so I can secure access to user data. Acceptance Criteria - Given an user is logged into their admin dashboard - When they navigate to security settings - Then they can see an option to enable 2FA - And they can choose between SMS or authenticator app methods - Given an user enables 2FA - When they log in with correct credentials - Then they are prompted for a verification code - And they must enter the correct code to access the dashboard - And backup codes are provided for recovery - Given an user enters an incorrect 2FA code - When they attempt to log in - Then access is denied with clear error messaging - And they can retry or use backup codes Technical Requirements Frontend: - Add 2FA setup flow to user settings page - Implement QR code display for authenticator apps - Create verification code input component - Add backup codes display and download Backend: - Implement TOTP (Time-based One-Time Password) generation - Add SMS integration for code delivery - Create 2FA verification middleware - Generate and store encrypted backup codes - Update authentication flow Definition of Done - 2FA setup UI implemented with tests - TOTP and SMS verification backend - Authentication middleware updated - Backup code system implemented - Security audit completed - User documentation updated - Error handling and edge cases covered - Code review approved Backend: TOTP generation, SMS integration, verification middleware, encrypted backup codesDefinition of Done2FA UI with testsBackend verification systemSecurity audit completedDocumentation updatedCode review approved

The claude story command generates complete user stories following XYZ team conventions.

2. Repository & Folder Overview

CLAUDE.md describes the repo structure, so Claude Code knows boundaries and avoids breaking shared code. The snippet below describes the structure of a simple monorepo:

apps/frontend/ (Next.js + React)api/ (GraphQL APIs)infrastructure/ (CDK scripts)packages/auth/, logging/, design-system/, shared-utils/Root configs: package.json, pnpm-workspace.yaml, turbo.json, CODEOWNERS

This allowed safe cross-package edits. For instance, when I updated a shared UI component, Claude Code warned about references in multiple apps and suggested minimal safe changes.

3. Technology Stack Awareness

Listing the stack helps Claude Code generate code correctly:

Backend: NestJS + Fastify, Apollo GraphQL, Prisma, CognitoFrontend: Next.js, React, StorybookInfrastructure: AWS CDK, Terraform CDKTesting: VitestPackage management: pnpm, Changesets

Claude Code now creates modules, resolvers, and schemas in the correct style. It avoids using outdated patterns.

4. Team & Project Context

Team ownership and ticket codes:

Team A: Team A featuresTeam B: Team B featuresTeam C: Team C workflows

For each team:

CODEOWNERS for automatic reviewTicket prefixes for JiraCross-team dependencies

This enables Claude Code to link PRs and stories correctly, notify the right people, and summarize cross-team changes accurately.

5. Development Workflow & Best Practices

Branch naming, pre-commit hooks, testing, and deployment rules:

Branch naming: feature/TEAM-123-descriptionPre-commit & CI/CD: linting, type checks, Vitest coverage, changesetsTesting: unit, integration, E2EDeployment: auto to dev/UAT, manual to prodStory integration: Jira ticket, Confluence links, design docs

Claude Code could scaffold feature branches, generate tests, and remind me of deployment steps consistently.

6. Story Creation & Acceptance Criteria

The following snippet tells Claude Code to generate stories in a structured format:

"As a [stakeholder], I want [action] so that [benefit]"Acceptance Criteria: functional requirements, UI/UX expectations, data handling, performance, edge cases, error handling, testing requirements

Every story is complete, consistent, and QA-ready.

7. Pull Request, Commit, & Changeset Guidelines

Commit format: <jira-ticket-number>: descriptionPRs: ticket link, documentation link, screenshots, checklist for tests, lint, coverage, and changesets

Claude Code uses these guidelines to ensure consistency and compliance with team conventions, reducing errors from missing PR steps, version mismatches, or incomplete documentation.

8. Troubleshooting & Edge Cases

Build failures: pnpm localsetupTest failures: vitest --uiNode/npm issues: pnpm npkill, pnpm installTypeScript/lint errors: npm run check-types, npm run eslint:fix

Claude Code can now diagnose issues and propose fixes without human prompting for every failure.

How Claude Code Helped in the Monorepo

Cross-package edits, NestJS service scaffolding, React components, AWS CDK constructs, Vitest tests, and housekeeping scripts are quicker now. They also have fewer errors. Claude Code didn’t just generate code; it spotted edge cases I might miss. After I cleaned up by removing node_modules, it reminded me to rerun setup steps. This included reinstalling dependencies and rebuilding the workspace. These small nudges helped me avoid confusing errors later.

Claude also ensured consistency across the monorepo. It kept imports, configs, and build scripts aligned without manual searching. Claude helped me save time and reduce copy-paste errors. Whenever I needed help with patterns—like renaming environments, changing CI workflows, or adding scripts—he was always there.

Using a Separate MD for Legacy Repos (Highly Recommended)

Older repos often use old frameworks and patterns. A dedicated CLAUDE_LEGACY.md file helps capture this context. This way, both Claude and humans can work safely. Be sure to include steps such as:

  • Stack & version map
  • Run & debug instructions
  • Common failure modes
  • Known bugs / risky areas
  • Bug-fix playbook
  • Best practices
  • Upgrade notes
  • Deployment & rollback instructions
  • Glossary & domain terms

A Real Legacy Win: Fixing a Race Condition

In one of the legacy repos I was working on, a race condition had been lurking for months. Non-transactional calls caused data inconsistencies under concurrent requests. Claude looked over the code using CLAUDE_LEGACY.md. He suggested wrapping operations in a transaction. He explained how this fix worked and created tests in the old style. Hours of manual debugging were reduced to minutes.

The advantages:

  • Proposes minimal, focused changes
  • Respects legacy constraints
  • Writes tests matching existing style
  • Traces context and blame efficiently

Tasks that became easier:

  • Reading unfamiliar code
  • Locating the source of bugs
  • Writing minimal, low-risk fixes with tests
  • Adding documentation
  • Suggesting safe refactors

Fun Moments and Quirks

Occasionally, Claude Code adds emojis or praise in PRs. It’s harmless and can be silenced via a line in CLAUDE.md. Claude Code has some short-term memory loss. It can act senile at times. It forgets instructions, misses past context, or needs reminders to stick to templates and the CLAUDE.md guidelines. This quirk means you often have to nudge it back on track, but it’s part of the charm—and a reminder that human review is still essential.

Claude Code vs. Copilot vs. Cursor: Where Each Shines

Having used all three, the differences are clear:

  • Claude Code: CLI-first, excels in structured repos with CLAUDE.md. Handles PRs, cross-package edits, scaffolding, and legacy fixes. Needs explicit context and structured prompts—like a senior dev wanting the full design doc first.
  • Copilot: Ideal for inline completions and boilerplate inside the IDE. Quick for snippets but limited for cross-file or repo-wide tasks.
  • Cursor: Reads the full repo and applies context-aware edits directly in the IDE. Plug-and-play, avoids token issues, and excels at large-scale refactors.

Summary Table:

A heatmap table comparing three coding tools: Claude Code, Copilot, and Cursor across five key features. The table uses color coding with pastel green for positive ratings (Excellent, Very High, High, Yes), pastel red for negative ratings (Weak, Low, No), yellow for warnings (Tight & Costly), gray for not applicable items, and purple for use cases. The table shows Claude Code scoring High in Repo Awareness, Excellent in Cross-Package Edits, Yes for Automated PR Workflow, but Tight & Costly for Token Limits, with best use case being Structured repos. Copilot shows Low Repo Awareness, Weak Cross-Package Edits, No Automated PR Workflow, Not applicable Token Limits, suited for Autocomplete & snippets. Cursor displays Very High Repo Awareness, Excellent Cross-Package Edits, No Automated PR Workflow, Not an issue for Token Limits, ideal for IDE Refactors. A color legend explains the coding system, showing six categories from Excellent/Very High to Use Cases.

Claude Code excels in monorepos and workflow automation. Copilot is great for quick inline coding. Cursor works well for context-heavy IDE edits. Used together, they cover nearly every development scenario efficiently.

What’s Next

The next steps focus on embedding Claude Code more deeply into everyday workflows while keeping context and safety in mind. Key actions include:

  • Iterative improvement of CLAUDE.md and CLAUDE_LEGACY.md: Treat these files as living documents. Update them with new patterns, commands, and edge cases discovered during work.
  • Monitoring AI suggestions: Collect feedback on where Claude Code’s outputs may introduce over-engineering, unnecessary mocks, or risk in legacy code.
  • Integration with Jira/GitHub pipelines: Explore automated story generation, PR creation, and testing reminders directly in ticket workflows.
  • Training new developers: Use CLAUDE.md as a learning guide so newcomers can quickly understand repo structure, conventions, and testing expectations.
  • Tracking impact: Measure how much time Claude Code saves, how many errors are prevented, and how stories/PRs improve in quality and consistency.

The goal is to shift Claude Code from helping with small tasks to being a dependable, context-aware partner. This change will speed up development and cut down on errors.

Final Thoughts

Claude Code won’t replace the thinking, intuition, or judgment that developers bring to a project. What it does is amplify those abilities. Claude Code works like a teammate. It understands the history, patterns, and limits of the codebase. You’ll find CLAUDE.md in a monorepo and CLAUDE_LEGACY.md for older repos.

Key takeaways:

  • Be specific in your prompts. Clear instructions lead to predictable, safe outputs.
  • Maintain accurate context files for both modern and legacy repos.
  • Treat AI as a team-aware assistant, not a magic wand; human review remains essential.
  • Continuously iterate on prompts, documentation, and workflows based on wins and lessons learned.

Claude Code can speed up feature development, cut down errors, boost testing and PR quality, and serve as a smart companion for both old and new code. It’s not about replacing developers—it’s about making each developer more effective and informed.

Top comments (0)