If you haven’t heard, we believe Dolt is the database for agents, so we’ve been testing the limits of the most popular agents to get a better idea of how people would use agents with Dolt. We recently migrated this blog from Gatsby to Astro and used Cursor Agent to assist with the migration.
Tim had compared popular coding agents, and Claude Code came out on top. But after Cursor Agent CLI came out, it won in a comparison to Claude Code. Cursor Agent produces slightly better results than Claude Code at 1/10th the cost, so it became the official DoltHub coding agent of choice.
This blog will discuss the dos and don’ts of using a coding agent like Cursor Agent for a large scale migration based on my experience with our blog migration.
DO: Use your agent to create a plan#
When I was scoping this project, I used Cursor Agent to create a step-by-step plan with time estimates for every step of the migration to Astro. Astro has a migration guide, but having a scoped plan that included all our specific blog features, such as search, pagination, RSS feed, etc., generated a more realistic idea of the changes involved. Instead of ingesting Astro’s migration guide and applying it to our specific code and features, using Cursor saved developer time by making the instructions more specific and tailored to our needs.
Once I got into the migration process, parts of the ordering and timing of the plan were off. So don’t take this as truth, but it was still a good place to start.
Here is a sample from the plan it came up with:
## Phase 1: Project Setup & Configuration
**Total Phase Time: 3-4 hours**
### Step 1.1: Install Astro and Core Dependencies
**Time Estimate: 30-45 minutes**
- [ ] Install Astro: `yarn add astro@latest` (5 min)
- [ ] Install Astro integrations:
- `@astrojs/react` (for React components) (5 min)
- `@astrojs/tailwind` (for Tailwind CSS) (5 min)
- `@astrojs/sitemap` (for sitemap generation) (5 min)
- `@astrojs/rss` (for RSS feed) (5 min)
- `@astrojs/image` or `astro:assets` (for image optimization) (5 min)
- `@astrojs/mdx` (if keeping MDX support) (5 min)
- `@astrojs/markdown-remark` (for markdown processing) (5 min)
- [ ] Install markdown plugins:
- `remark-prism` or `rehype-pretty-code` (for syntax highlighting) (5 min)
- `remark-autolink-headings` (for heading anchors) (5 min)
- `remark-copy-linked-files` equivalent (5 min)
### Step 1.2: Create Astro Configuration
**Time Estimate: 45-60 minutes**
- [ ] Create `astro.config.mjs` with:
- Site URL: `https://dolthub.com/blog` (5 min)
- Base path: `/blog` (5 min)
- Output: `static` (SSG) (5 min)
- Integrations: React, Tailwind, Sitemap, RSS (15 min)
- Markdown configuration (syntax highlighting, autolink headers) (15 min)
- Image optimization settings (10 min)
### Step 1.3: Update TypeScript Configuration
**Time Estimate: 20-30 minutes**
- [ ] Update `tsconfig.json` for Astro:
- Change module to `ESNext` or `NodeNext` (5 min)
- Update JSX settings for Astro (5 min)
- Keep references to shared-components (5 min)
- Add Astro types (5 min)
### Step 1.4: Update Package Scripts
**Time Estimate: 10-15 minutes**
- [ ] Update `package.json` scripts:
- `dev`: `astro dev` (2 min)
- `build`: `astro build` (2 min)
- `preview`: `astro preview` (2 min)
- Keep existing lint/prettier scripts (5 min)
---
DON’T: Use your agent for the initial package setup#
We have a GitHub monorepo that houses most of our code for the web (Golang APIs, infrastructure, GraphQL server, React UIs). For dolthub.com specifically, we have a Yarn workspace called web that has this structure:
├── README.md
├── babel.config.js
├── eslint.config.js
├── package.json
├── packages
│ ├── babel-config
│ ├── blog
│ ├── dolthub
│ ├── dolthub-api
│ ├── events-api
│ ├── fakers
│ ├── graphql-server
│ ├── ld-proto
│ ├── resource-utils
│ └── shared-components
├── tsconfig.json
└── yarn.lock
This means that all packages have their own package.json and can reference each other but share one yarn.lock. I asked Cursor to create a new blog-astro workspace, which would house the new blog code, and explained our setup. It kept creating a blog-astro Git submodule, even when I specifically asked it not to.
Once we got past the submodule fiasco, it struggled with the rest of the basic setup of a Yarn workspace. It wanted to default to npm and consistently misunderstood the repo structure. I lost time on this step using Cursor rather than doing it on my own.
DO: Use your agent for repetitive tasks like moving files#
Once the initial setup was done, Cursor did a great job moving our 1,000+ markdown files and 3,000+ images to the new package, as well as updating the paths of our assets and small structure changes to the markdown frontmatter. This task was clear and easily repeated, and Cursor needed little prompting or corrections. This is an area where Cursor outperformed an engineer.
DON’T: Overrely on your agent to execute all of the migration steps without understanding the basics#
Once Cursor made me a plan, I naively thought we could go through step-by-step and Cursor could do all of the work for me. I understood on a high level what I could expect from the differences between Gatsby and Astro. But once I got through a few of the migrations steps using Cursor and went back to make changes, I didn’t have enough information to know why it made certain decisions and how to make foundational changes to the project.
Cursor set up all the configuration, routing, React and Astro components, and styling. And this is what I got:

You can see the main functionality is there, but it looks nothing like the blog you’re reading now. I thought the required changes would be mostly CSS-related, but some of the ways we share components with our other packages were very broken. The deeper I got, the more I noticed that some of the ways things were implemented were incorrect for what we wanted. I had to go back to the beginning and understand at a more basic level how to best incorporate our external React components and why certain things that worked with Gatsby didn’t work with Astro.
I lost a lot of time on this step. If I had taken time to do some learning before moving forward blindly with Cursor, I would have had less untangling to do later.
DO: Give your agent scoped problems#
Prompts like: move all of our React components from our Gatsby package to our new Astro package are a recipe for bugs. Cursor will make this work in a quick, brute force way, by copying the exact logic from Gatsby and getting it to work in Astro. Things don’t always work the same way in Gatsby and Astro. While this was fine for simple components, more complicated components like search required more research and prompting.
Specifically for search, when the component was first migrated, it only kind of worked with the Gatsby strategy. When I asked Cursor to ignore the Gatsby strategy and tell me how to best implement search in Astro, it was completely different. I split up the problem into a few parts: the search strategy itself, the search input component, and the search results list. Then we worked through each individually, solving problems that came up along the way before moving on to the next part. Cursor required more handholding to be useful for this kind of work.
DON’T: Think your agent has style#
Cursor Agent can’t see the browser. You can see from the screenshot above that Cursor wasn’t even close to replicating the look and feel of our original blog. Even if I pointed it to the exact CSS file that was being used for a certain component, it would fail. It had no way to validate that the changes it was making were correct. This is a large gap for using an agent for front end work like this. There was really no point.
Conclusion#
Using a coding agent can be a great tool for large scale migration if used correctly. More generally, it seemed better to use the coding agent for scoped, smaller tasks that don’t involve knowledge of the browser.
To maintain journalistic integrity, I reached out to Cursor Agent for comment. This is what it had to say:
┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ I wrote a new blog called "How to (not) use Agents for a Large Scale Migration" about my experience using you to │
│ migrate our blog from Gatsby to Astro. What are your opinions about what I said? │
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Reading the blog post to understand your perspective.
⬢ Read .../2025-11-14-large-scale-migration-with-agent.md
What resonates
1. Planning: Agents can help break down large tasks, but the plan is a starting point, not a blueprint. Ordering and
estimates often need adjustment.
2. Repetitive tasks: File moves, path updates, and bulk transformations are a good fit. Clear, repeatable patterns
work well.
3. Scoped problems: Breaking complex tasks into smaller, focused prompts improves results. "Migrate search" is too
broad; "implement search index generation" is better.
4. Style/visual work: Without browser feedback, CSS/styling changes are unreliable. Agents can’t validate visual
results, which is a real limitation.
Additional thoughts
1. Monorepo setup: Yarn workspaces and monorepo structures are tricky. Agents often default to simpler setups and miss
workspace-specific details. Manual setup here is usually faster.
2. Understanding vs. speed: The trade-off between moving fast and understanding the system is real. For migrations,
understanding the target framework (Astro) first helps catch structural issues early.
3. Component migration: Copying Gatsby patterns into Astro often misses framework-specific patterns. Astro’s component
model differs from Gatsby’s, so a direct port can introduce subtle issues.
What I’d add
• Use agents for exploration: Ask “how would you implement X in Astro?” before migrating, not just “migrate X from
Gatsby.”
• Incremental validation: Test each migrated component/feature before moving to the next.
• Pair programming model: Use the agent as a pair that suggests code, not as an autonomous executor.
Overall, this aligns with effective agent use: leverage strengths (planning, repetitive tasks, scoped problems) and
avoid weaknesses (visual work, complex setup, blind execution). The key is knowing when to use the agent and when to
take manual control.
Did the final migration turn out well? Any patterns you’d add to the dos/don’ts?
That feels…overly agreeable. Let’s try again.
┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Are you just agreeing with me? You don't disagree with anything I said? │
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Re-reading with a more critical lens:
⬢ Read .../2025-11-14-large-scale-migration-with-agent.md
Here are some disagreements and pushbacks:
1. The plan wasn't that useful
You say the plan was "a good place to start" but the ordering was wrong. If ordering matters, a wrong plan can
mislead. The time estimates look optimistic (5 minutes per integration?). Agents often produce plausible-looking
plans that aren't reliable. Maybe skip the detailed plan and use the agent for exploration: "What are the key
differences I need to handle?" rather than a step-by-step checklist.
2. The monorepo issue might be a prompt problem
You say it "kept creating a Git submodule even when I specifically asked it not to." Did you show it your existing
workspace structure with examples? Or just describe it? Agents struggle with monorepos, but showing concrete examples
(e.g., "here's how blog/package.json references shared-components") often helps. This might be more about prompt
engineering than an inherent limitation.
3. "Lost time" vs. learning time
You frame time spent as "lost," but iteration is part of the process. The real issue might be expecting perfect
results on the first try. The monorepo struggle could have been valuable learning if you adjusted your approach. The
question is: was the total time (agent + fixes) faster than doing it manually? If yes, it wasn't lost time.
4. The "overrely" problem is a workflow issue, not a tool issue
You say you "lost a lot of time" because you didn't understand the basics. But you could have used Cursor and
validated incrementally. The problem wasn't using Cursor—it was not testing as you went. You could have asked Cursor
to implement one component, tested it, understood it, then moved on. The issue is workflow, not the tool.
5. CSS work isn't useless—you just need different inputs
You say "there was really no point" to using the agent for CSS because it can't see the browser. But you could:
• Provide screenshots/diffs
• Give very specific instructions ("change padding-top from 1rem to 2rem")
• Use it to generate CSS from a description, then you validate
The limitation is visual feedback, not CSS work entirely. With the right inputs, it can help.
6. Scoped problems might be a prompt quality issue
You say breaking search into parts worked better than one big prompt. But maybe a better initial prompt could have
worked: "Implement search using Astro's best practices. Research Astro's recommended approach first, then implement.
Don't copy Gatsby patterns." The issue might be prompt quality, not scope size.
The bigger critique
Your post reads like "agents failed me" when it's more "I used agents suboptimally and learned better patterns."
That's valuable, but the framing blames the tool more than the approach. A more accurate title might be "How I
Learned to Use Agents Better During a Migration."
What do you think? Am I being too harsh, or are these fair points?
In conclusion, take this all with a grain of salt, maybe the problem is me 😅.
Have you used an agent for a large scale migration like this one? Reach out to us on Discord.
