Saltearse al contenido

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.mdc automá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:

  1. Abre el repo de Mi Plante: File > Open Folder > ext-miplante/

  2. 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.

  3. 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.mdc exista.

  4. Confirma que el autocompletado con Tab funciona. Abre app/Services/VentaService.php, pon tu cursor al final de obtenerV y espera. Cursor debería sugerir obtenerVenta u obtenerVentas (ambos métodos existen en este archivo).

  5. 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 marketplace
globs: ["**/*.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 reglas
  • globs: qué archivos activan esta regla. ["**/*.php", "**/*.ts", "**/*.vue"] significa cada archivo PHP, TypeScript y Vue en el repo
  • alwaysApply: 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 TransUnionLegalCheckService modelado en DataCreditoService, con un LegalCheckResultDTO correspondiente y un tests/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.vue modelada en Crear.vue. Agrega la ruta en routes/ally/web.php. Agrega el método del controller en EmpleadoController.”
  • Agregar un feature test. “Escribe un feature test bajo tests/Feature/Aliado/EmpresaUpdateTest.php que ejercite el endpoint existente PUT /aliados/empresas/{id}.”
  • Renombrar un símbolo no-de-dominio a través del código. “Renombra formatCOP a formatColombianPeso en todas partes excepto la definición en lib/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::generarCuotas y ProcesarPagareDigital::handle de 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.php

Ahora 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:

TareaUsarPor qué
Primera exploración de un área nuevaClaude CodeSlash commands como /explain-this-service cargan contexto rápido
Correr tests / lint / buildsClaude CodeLa herramienta Bash es de primera clase
Planeación multi-pasoClaude CodePuede encadenar reads, greps, edits en un turno
Bugfix de una sola líneaCursor (Cmd+K)Ciclo de diff más rápido
Edición de componente VueCursorLos diffs inline en el editor son más fáciles de revisar
Armar archivos nuevosCursor (Composer)Un round trip genera el set completo
Agregar un test nuevoCualquieraCursor si lo quieres junto al archivo; Claude Code si también quieres correrlo
Revisar un PR localmenteClaude CodeMás fácil preguntar “¿qué cambia este diff?” con herramientas de git al alcance
Refactorizar a través de muchos archivosCursor (Composer) con precauciónConfirma landmines primero vía Claude Code
Tarea de larga duración (p. ej. test de carga masiva, suite completa de tests)Claude CodeBash 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

  1. 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 usa obtenerVenta($id). Siempre lee la sugerencia antes de presionar Tab. Si un método no existe, la sugerencia compilará pero explotará en runtime.

  2. 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, GenerarCreditoDeVenta y ValidarPagareDigital simultá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.

  3. No leer .cursor/rules/mi-plante.mdc. Es corto. Léelo una vez. Te ahorra de muchos de los modos de falla documentados en 04-when-not-to-trust-the-ai.md.

  4. 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-approval en 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.

  5. Olvidar que el autocompletado con Tab lee archivos abiertos. Si el único archivo que tienes abierto es package.json y empiezas a escribir PHP en VentaService.php, tus completions con Tab serán inútiles. Abre 3-4 archivos relacionados antes de asentarte.

  6. Intentar usar Composer para una tarea que necesita Http::fake(). Composer armará un test, pero puede armar una clase DataCreditoMock que no existe. Siempre lee el test generado antes de aceptar. El patrón es Http::fake(['*/cs/credit-history/*' => Http::response([...], 200)]) contra el macro Http::datacredito().

  7. 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” $cliente a $customer en un diff generado. Recházalo. El estándar del equipo es español para dominio, inglés para infraestructura.

  8. 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 DataCreditoService

Claude 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 nuevo
  • app/DTOs/TransUnion/TransUnionCreditResultDTO.php — DTO nuevo
  • app/Providers/AppServiceProvider.php — registra el macro Http::transunionCredit()
  • config/services.php — agrega bloque de config transunion_credit
  • .env.example — agrega TRANSUNION_CREDIT_URL, TRANSUNION_CREDIT_USER, TRANSUNION_CREDIT_PASSWORD, TRANSUNION_CREDIT_CLIENT_ID, TRANSUNION_CREDIT_CLIENT_SECRET
  • tests/Unit/Services/TransUnionCreditServiceTest.php — test nuevo usando Http::fake()
  • Si el servicio debe exponerse vía un endpoint de controller, agrega eso a routes/api.php o routes/web.php dependiendo 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.

Ventana de terminal
git add app/Services/TransUnionCreditService.php app/DTOs/TransUnion/ app/Providers/AppServiceProvider.php config/services.php .env.example tests/Unit/Services/TransUnionCreditServiceTest.php
git 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ón
Cmd+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 indexados

Manté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.