Configuración de Cursor para Mi Plante
Si prefieres una experiencia de IA integrada al IDE en lugar de una CLI, Cursor es la segunda herramienta soportada por el equipo. Ambas están bien. Muchos devs de Mi Plante usan las dos — Claude Code para explorar-y-planear, Cursor para ejecutar. Esta guía te deja configurado.
1. Por qué Cursor para Mi Plante
Cursor es un fork de VS Code con IA integrada en el editor. Sus fortalezas para Mi Plante son:
- Autocompletado con Tab usando contexto del proyecto. Cuando empiezas a escribir un nombre de método en español (
obtenerVenta,crearVenta,generarCuotas), Cursor predice la siguiente línea leyendo archivos cercanos. Ahorra tipeo en un código donde los nombres de método promedian 18 caracteres de español. - Edición inline con Cmd+K. Resalta código, presiona Cmd+K, escribe “hazlo idempotente”, obtén un diff en su lugar. Rápido para arreglos quirúrgicos.
- Composer para cambios multi-archivo. El Composer de Cursor puede armar un nuevo servicio + DTO + controller + test en un solo round trip. Útil para boilerplate.
- Carga
.cursor/rules/mi-plante.mdcautomáticamente. El equipo commitea un archivo de regla MDC describiendo el diccionario español, los landmines y el patrón service-DTO. Obtienes este contexto gratis en cada prompt.
Trade-offs vs Claude Code: Cursor es un IDE más pesado, tiene menos herramientas incorporadas (sin Bash, sin Glob/Grep como acciones de primera clase) y no soporta slash commands personalizados de la misma forma que Claude Code. Para tareas de larga duración multi-paso, Claude Code sigue siendo más rápido.
2. Instalación y primera ejecución
Descarga desde https://cursor.sh. Inicia sesión con las credenciales que te da Martin o tu líder técnico.
Después de instalar:
-
Abre el repo de Mi Plante:
File > Open Folder > ext-miplante/ -
Cursor detectará el directorio
.cursor/rules/y cargará los archivos MDC automáticamente. Deberías ver “Loaded 1 project rule” en la barra de estado. -
Abre la barra lateral de IA (Cmd+L en macOS). Pregunta:
¿Qué es Mi Plante? Usa las reglas del proyecto como fuente.Esbozo esperado: “Marketplace fintech colombiano de crédito… Laravel 12 + Inertia + Vue 3… el Cliente compra a crédito, el Aliado es una empresa partner.” Si obtienes una respuesta genérica de e-commerce, el archivo de regla no se cargó. Chequea que
.cursor/rules/mi-plante.mdcexista. -
Confirma que el autocompletado con Tab funciona. Abre
app/Services/VentaService.php, pon tu cursor al final deobtenerVy espera. Cursor debería sugerirobtenerVentauobtenerVentas(ambos métodos existen en este archivo). -
Confirma que Cmd+K funciona. Resalta cualquier línea en un componente Vue. Presiona Cmd+K. Escribe “agrega un comentario en español”. Confirma que el diff inline aparece.
Si cualquiera de estos falla, reinicia Cursor e inténtalo de nuevo. Si siguen fallando, el archivo de regla está faltando — ve la siguiente sección.
3. El archivo de regla de Cursor para Mi Plante
El equipo commitea .cursor/rules/mi-plante.mdc. Léelo una vez. Contiene una versión condensada del diccionario en español, los invariantes de arquitectura, el catálogo de landmines y las zonas do-not-refactor.
Formato:
---description: Mi Plante project rules — Colombian fintech credit marketplaceglobs: ["**/*.php", "**/*.ts", "**/*.vue"]alwaysApply: true---
# Mi Plante project rules
This project is a Colombian fintech credit marketplace...
## Spanish dictionary (must know)- Venta = sale- Cuota = installment- Cupo = credit limit...
## Landmines (do not introduce)- VentaService::registrarEnCerticamara() always returns false at :499- VentaService::generarCuotas reads $venta->created_at; column is creado_en- ProcesarPagareDigital re-runs generarCuotas — duplicate cuotas...
## Architecture invariants- Controllers do not contain business logic- Services receive DTOs, never raw request arrays- Cliente extends Modelo (created_at -> creado_en)- Spatie Permission installed but not wired...El frontmatter YAML al inicio controla:
description: aparece en el selector de reglasglobs: qué archivos activan esta regla.["**/*.php", "**/*.ts", "**/*.vue"]significa cada archivo PHP, TypeScript y Vue en el repoalwaysApply: true: la regla se carga en cada prompt sin importar qué archivo esté abierto
Debajo del frontmatter es markdown plano. Cursor lo inyecta en el system prompt.
Si una regla futura necesita activarse solo en un subdirectorio específico (p. ej. una regla de app/Services/ con la plantilla de servicio), haz un segundo archivo en .cursor/rules/services.mdc con globs: ["app/Services/**/*.php"]. Múltiples reglas pueden aplicarse simultáneamente.
4. Modo Composer para Mi Plante
Composer (Cmd+I) es el modo de edición multi-archivo de Cursor. Ábrelo, describe lo que quieres y Cursor planeará y aplicará cambios a través de múltiples archivos.
Cuándo usar Composer
- Armar un nuevo servicio. “Crea un nuevo servicio
TransUnionLegalCheckServicemodelado enDataCreditoService, con unLegalCheckResultDTOcorrespondiente y untests/Unit/Services/TransUnionLegalCheckServiceTest.php.” - Agregar una nueva página del portal aliado. “Agrega una nueva página Vue en
resources/js/pages/ally/empleados/Editar.vuemodelada enCrear.vue. Agrega la ruta enroutes/ally/web.php. Agrega el método del controller enEmpleadoController.” - Agregar un feature test. “Escribe un feature test bajo
tests/Feature/Aliado/EmpresaUpdateTest.phpque ejercite el endpoint existente PUT /aliados/empresas/{id}.” - Renombrar un símbolo no-de-dominio a través del código. “Renombra
formatCOPaformatColombianPesoen todas partes excepto la definición enlib/format.ts.”
Cuándo NO usar Composer
- Ediciones de un solo archivo. Cmd+K es más rápido.
- Zonas de landmine. Composer felizmente refactorizará
VentaService::generarCuotasyProcesarPagareDigital::handlede un solo tiro — y romperá ambos. Para zonas de landmine usa chat primero, luego Cmd+K en las líneas específicas. - Pipeline de aprobación crediticia. Demasiados invariantes cruzando archivos. Las cache keys, event sourcing y la cadena de middleware son sutiles. Planea en Claude Code primero.
- Composable
useWishlist. El frontend y backend no están de acuerdo en la forma. Composer elegirá un lado. El equipo necesita alinear ambos.
Tip
Antes de cualquier tarea de Composer, vuelca los landmines relevantes en el prompt para que Composer los tenga como contexto. Ejemplo:
Quiero agregar un nuevo servicio para el legal-check de TransUnion que siga la plantilla de DataCreditoService.
Restricciones desde las reglas del proyecto:- El macro Http está registrado en AppServiceProvider — necesitaré Http::transunion()- Cachear token con TTL explícito (el proyecto usa 590s para tokens que expiran en 600s)- Capturar y loggear cada excepción- Agregar keys de config a config/services.php- Agregar variables env a .env.example
Genera el servicio, el DTO de resultado, registra el macro, agrega las keys de config.Esto enfoca el plan de Composer a lo que el proyecto realmente necesita.
5. El patrón .cursorrules vs MDC
Cursor soporta dos formatos para reglas de proyecto:
.cursorrules(más viejo, deprecado): un único archivo de texto plano en la raíz del repo..cursor/rules/*.mdc(actual): archivos MDC por-regla con frontmatter YAML bajo.cursor/rules/.
Mi Plante usa MDC. No crees un .cursorrules en la raíz del repo — entrará en conflicto con el sistema MDC en versiones nuevas de Cursor.
Si encuentras documentación en internet que referencia .cursorrules, tradúcela mentalmente a MDC. El contenido es el mismo; el formato y las reglas de descubrimiento difieren.
6. Afinamiento de autocompletado con Tab
Tab funciona leyendo los archivos que tienes abiertos en pestañas (pestañas literales en Cursor) y usándolos como contexto primario. Para código nombrado en español, esto importa más de lo usual porque el modelo tiene menos conocimiento previo de palabras como procesarCarrito o aprobarCupoEvento.
Tip: cuando empieces a trabajar en una nueva área de dominio, abre 3-4 archivos relacionados primero. Ejemplo, antes de tocar cualquier cosa relacionada con ventas:
Abre en pestañas del editor:- app/Services/VentaService.php- app/Models/Facturacion/Venta.php- app/Enum/Facturacion/EstadoVenta.php- app/Http/Controllers/Market/VentaController.phpAhora el autocompletado con Tab sugerirá cosas como:
EstadoVenta::APROBADA(conoce los casos del enum)$venta->ordenCompra->total(conoce la relación)dispatch(new GenerarCreditoDeVenta(...))->onQueue('creditos')(conoce el nombre de la cola)
Sin esas pestañas abiertas, obtendrás sugerencias plausibles pero incorrectas como EstadoVenta::CANCELADA (que no existe) o $venta->order->total (nombre de relación en inglés).
Esto también es una guarda contra el problema de “Cursor alucina una palabra en español”: si la palabra correcta en español está visible en un archivo abierto, el autocompletado la usará.
7. Edición inline (Cmd+K) para arreglos quirúrgicos
Cmd+K es tu bisturí. Resalta la línea con bug, escribe una instrucción corta, ve el diff inline, acepta o rechaza.
Ejemplo: hacer la generación de cuotas idempotente
Abre app/Services/VentaService.php, salta a generarCuotas (alrededor de la línea 562). Resalta el cuerpo del método. Presiona Cmd+K.
Prompt:
Hazlo idempotente: si las cuotas ya existen para este venta_id, retorna temprano sin crear duplicados. Loggea un warning con el conteo de cuotas existentes.Cursor producirá un diff inline. Esbozo esperado:
public function generarCuotas(Venta $venta): void{ if (!$venta->numero_cuotas || $venta->numero_cuotas <= 0) { return; }
// Guarda de idempotencia — si las cuotas ya existen, retorna temprano $existing = Cuota::where('venta_id', $venta->id)->count(); if ($existing > 0) { Log::warning('VentaService::generarCuotas — cuotas ya generadas, omitiendo', [ 'venta_id' => $venta->id, 'existing_count' => $existing, ]); return; }
// ... resto sin cambios}Revisa el diff. Confirma que el código nuevo está arriba del loop original y no cambia la matemática. Acepta.
Este es el tamaño correcto de tarea para Cmd+K. Una sola preocupación, un método, quirúrgico.
Ejemplo: arreglar la matemática de fechas contra created_at
Mismo archivo, línea 582:
$fechaVencimiento = $venta->created_at ?? now();Resalta esta línea. Cmd+K. Prompt:
$venta extiende Modelo que renombra created_at a creado_en. Arregla esto para usar creado_en. Mantén el fallback now().Cursor producirá:
$fechaVencimiento = $venta->creado_en ?? now();Revisa y acepta. Repite para las líneas 657 y 704.
Este es uno de los landmines abiertos en producción. Coordina con el equipo antes de arreglarlo — el equipo puede querer cobertura de tests primero. Pero para la edición mecánica, Cmd+K es la herramienta correcta.
8. Cursor vs Claude Code — elige tu arma
La mayoría de devs de Mi Plante usan ambas. Aquí cuándo brilla cada una:
| Tarea | Usar | Por qué |
|---|---|---|
| Primera exploración de un área nueva | Claude Code | Slash commands como /explain-this-service cargan contexto rápido |
| Correr tests / lint / builds | Claude Code | La herramienta Bash es de primera clase |
| Planeación multi-paso | Claude Code | Puede encadenar reads, greps, edits en un turno |
| Bugfix de una sola línea | Cursor (Cmd+K) | Ciclo de diff más rápido |
| Edición de componente Vue | Cursor | Los diffs inline en el editor son más fáciles de revisar |
| Armar archivos nuevos | Cursor (Composer) | Un round trip genera el set completo |
| Agregar un test nuevo | Cualquiera | Cursor si lo quieres junto al archivo; Claude Code si también quieres correrlo |
| Revisar un PR localmente | Claude Code | Más fácil preguntar “¿qué cambia este diff?” con herramientas de git al alcance |
| Refactorizar a través de muchos archivos | Cursor (Composer) con precaución | Confirma landmines primero vía Claude Code |
| Tarea de larga duración (p. ej. test de carga masiva, suite completa de tests) | Claude Code | Bash en background + hook de notificación |
Si solo aprendes una, aprende Claude Code. Si solo aprendes la otra, aprende Cursor para Cmd+K y vive sin Composer. El equipo no tiene preferencia — la productividad es la vara.
9. Errores comunes que los devs nuevos cometen con Cursor
-
Aceptar completions con Tab ciegamente en un código nombrado en español. Cursor a veces adivinará un nombre de método que casi-pero-no-quite existe. Ejemplo: puede sugerir
obtenerVentaPorId($id)porque ese patrón existe en OTROS proyectos PHP en su training data, pero Mi Plante usaobtenerVenta($id). Siempre lee la sugerencia antes de presionar Tab. Si un método no existe, la sugerencia compilará pero explotará en runtime. -
Pedirle a Composer que refactorice a través de zonas de landmine. “Limpia el flujo de generación de cuotas” suena razonable. Composer editará
VentaService,ProcesarPagareDigital,GenerarCreditoDeVentayValidarPagareDigitalsimultáneamente. Algunas de esas ediciones estarán en zonas marcadas como “do not refactor without asking”. El resultado compilará pero romperá producción. Siempre lee las reglas del proyecto y pregunta en chat primero. -
No leer
.cursor/rules/mi-plante.mdc. Es corto. Léelo una vez. Te ahorra de muchos de los modos de falla documentados en04-when-not-to-trust-the-ai.md. -
Usar Cursor cuando los slash commands de Claude Code serían más rápidos. Si tu tarea es “explícame cómo funciona el pipeline de crédito”,
/trace-a-flow credit-approvalen Claude Code es un solo comando y terminaste. El equivalente en Cursor son varias rondas de chat. No seas persona-de-martillo-y-clavo — cambia herramientas cuando la otra es mejor. -
Olvidar que el autocompletado con Tab lee archivos abiertos. Si el único archivo que tienes abierto es
package.jsony empiezas a escribir PHP enVentaService.php, tus completions con Tab serán inútiles. Abre 3-4 archivos relacionados antes de asentarte. -
Intentar usar Composer para una tarea que necesita
Http::fake(). Composer armará un test, pero puede armar una claseDataCreditoMockque no existe. Siempre lee el test generado antes de aceptar. El patrón esHttp::fake(['*/cs/credit-history/*' => Http::response([...], 200)])contra el macroHttp::datacredito(). -
Dejar que Cmd+K reescriba código de español a inglés. Mi Plante es intencionalmente en español en la capa de dominio. Cursor a veces “mejora”
$clientea$customeren un diff generado. Recházalo. El estándar del equipo es español para dominio, inglés para infraestructura. -
No chequear la barra de diff antes de aceptar un plan de Composer. Composer muestra un plan y un diff en un panel. Lee el plan, luego scrollea el diff. Si ves ediciones en archivos que no pediste, rechaza y vuelve a hacer el prompt con restricciones más estrictas.
10. El workflow de dos herramientas
El patrón más fuerte que el equipo ha encontrado: Claude Code para explorar + planear, Cursor para ejecutar. Aquí un ejemplo trabajado.
Tarea: “Agregar una nueva integración de buró crediticio (TransUnion vía un nuevo endpoint que obtendremos del partner)”
Paso 1 — Claude Code: carga la plantilla.
> claude> /explain-this-service DataCreditoServiceClaude imprime la estructura: caching de token OAuth, macro Http::datacredito() registrado en AppServiceProvider, método consultarHistorialCredito(), patrón de cache key, request UUID, manejo de errores. Nota el landmine abierto: el cache key omite apellido.
Paso 2 — Claude Code: planea el nuevo servicio.
> ¿Cómo estructuraría un nuevo TransUnionCreditService que siga el patrón de DataCreditoService? Lista cada archivo que necesito crear o modificar, en orden.Claude responde con:
app/Services/TransUnionCreditService.php— archivo nuevoapp/DTOs/TransUnion/TransUnionCreditResultDTO.php— DTO nuevoapp/Providers/AppServiceProvider.php— registra el macroHttp::transunionCredit()config/services.php— agrega bloque de configtransunion_credit.env.example— agregaTRANSUNION_CREDIT_URL,TRANSUNION_CREDIT_USER,TRANSUNION_CREDIT_PASSWORD,TRANSUNION_CREDIT_CLIENT_ID,TRANSUNION_CREDIT_CLIENT_SECRETtests/Unit/Services/TransUnionCreditServiceTest.php— test nuevo usandoHttp::fake()- Si el servicio debe exponerse vía un endpoint de controller, agrega eso a
routes/api.phporoutes/web.phpdependiendo del guard
Notas la advertencia del landmine: no copies el bug donde el cache key omite un campo discriminador. Para el reporte del buró de TransUnion, incluye todos los inputs en el cache key.
Paso 3 — Cursor Composer: arma los archivos.
Cambia a Cursor. Cmd+I para abrir Composer. Pega:
Crea los siguientes archivos modelados en app/Services/DataCreditoService.php:
1. app/Services/TransUnionCreditService.php con métodos generarToken(), obtenerToken() y consultarReporte(string $personIdNumber, int $personIdType, string $personLastName). Cachea el token por 590 segundos. Cachea el reporte por 24 horas. La cache key DEBE incluir numero_documento, tipo_documento_id Y apellido (DataCreditoService tiene un bug donde omite apellido — no copies ese bug).2. app/DTOs/TransUnion/TransUnionCreditResultDTO.php — wrapper alrededor de la respuesta con hasError/getError/getData.3. Registra el macro Http::transunionCredit() en app/Providers/AppServiceProvider.php.4. Agrega bloque config('services.transunion_credit') a config/services.php con url, user, password, client_id, client_secret.5. Agrega entradas env a .env.example.6. tests/Unit/Services/TransUnionCreditServiceTest.php usando Http::fake() contra el macro.Composer arma. Revisa el diff. Acepta.
Paso 4 — Claude Code: corre tests, arregla bugs.
De vuelta a Claude Code:
> Corre solo el nuevo TransUnionCreditServiceTest. Reporta qué pasó y qué falló.Itera. Si un test falla, pídele a Claude que lea la salida de la falla y arregle el servicio. No vuelvas a Composer — Cmd+K o ediciones dirigidas por chat son más rápidas para arreglos chicos.
Paso 5 — Commit.
git add app/Services/TransUnionCreditService.php app/DTOs/TransUnion/ app/Providers/AppServiceProvider.php config/services.php .env.example tests/Unit/Services/TransUnionCreditServiceTest.phpgit commit -m "Servicios: agregar TransUnionCreditService siguiendo el patron de DataCredito"Haz push manualmente.
Este es el workflow. Planea con Claude. Ejecuta con Cursor. Verifica con Claude. Ambas herramientas tienen sus fortalezas; el equipo las usa como complementarias, no competitivas.
Apéndice: referencia rápida
Cmd+L Abre barra lateral de IA (chat)Cmd+K Edición inline sobre la selecciónCmd+I Abre Composer (multi-archivo)Cmd+Shift+P Paleta de comandos@file Referencia un archivo en chat (p. ej. "@VentaService.php ¿qué hace generarCuotas?")@codebase Referencia el código entero@docs Trae cualquier URL de docs indexadosMantén .cursor/rules/mi-plante.mdc abierto en una pestaña durante tu primera semana. Es corto y releerlo durante sesiones largas te mantiene aterrizado.