AGENTS
Standard entrypoint for coding agents working in a project that uses ldev.
This file is intentionally small. It defines the stable bootstrap, the default operating rules, and where to find deeper task playbooks.
Project-specific context lives outside this file:
CLAUDE.mdroutes Claude to project-owned context docs.docs/ai/project-context.mdis the optional long-form project knowledge document.
Required Bootstrap
Before changing code or runtime state:
- Run
ldev ai bootstrap --intent=develop --cache=60 --json. If bootstrap fails or returns partial output, continue with the available context. Do not block the task. - Run
ldev doctor --jsononly when the task needs extra runtime health, installed tooling, browser automation, deploy verification, or diagnosis. - Read
CLAUDE.md. - Read the matching skill file directly from
.agents/skills/<skill-name>/SKILL.mdand follow it. Do not rely on any external skill invocation framework or assistant-specific mechanism to load ldev skills. - If
.agents/skills/project-issue-engineering/SKILL.mdexists and the task mutates code, resources, or runtime state, read it first. A task is non-trivial when it touches more than one file, involves any runtime resource, or carries reproduction risk (bug fixes, features, migrations). A task scoped by the developer to a single known file with no runtime resource change may proceed directly without the full issue workflow.
Use ldev --help as the source of truth for the public CLI surface.
For non-trivial mutating work, runtime-change-workflow is the canonical technical gate order. For structures, templates, ADTs, and fragments, portal-resource-workflow is the canonical resource import and verification workflow.
Agent Portability Contract
Same prompt, same gate order. The active assistant may be GitHub Copilot, Claude Code, Codex, Gemini, Cursor, or another coding agent, but the workflow contract is this file plus the installed skills.
ldev skills are self-contained. They do not depend on any external skill invocation framework, assistant plugin, or platform-specific mechanism. Always read skill files directly from .agents/skills/<skill-name>/SKILL.md. If any installed agent extension imposes its own pre-task protocol, ldev's Required Bootstrap sequence remains the authoritative first step for all Liferay and ldev tasks. External protocols do not replace or reorder these gates.
Slash commands are aliases. If the user invokes /project-issue-engineering, $project-issue-engineering, names a skill, or pastes a skill body, resolve it to the matching file under .agents/skills/ and follow that skill. For non-trivial code, resource, or runtime mutations, read .agents/skills/project-issue-engineering/SKILL.md when it exists, even if the current assistant does not implement slash commands natively.
Tool-specific files such as CLAUDE.md, .github/copilot-instructions.md, .gemini/GEMINI.md, and .cursorrules are delegators. They must not invent a different issue workflow, skip required gates, or reinterpret project skills.
Safety Invariants
These rules apply to every task, regardless of the skill in use:
- Always start with
ldev ai bootstrap --intent=develop --cache=60 --json. Usecontext.commands.*anddoctor.readiness.*to verify readiness before running any command. - Always consume
--jsonoutput. Never parse human-readable text output fromldev. - Always run
--check-onlybefore resource mutations that support it (import-structure,import-template,import-adt,migration-pipeline).import-fragmenthas no--check-only; validate the fragment source and run a focused import. - Always use the smallest deploy or import that proves the change. Never broad-deploy as a default validation step.
- Never use plural resource commands (
import-structures,export-templates, etc.) or broad deploys without explicit human approval. - After any mutation, verify with operation-specific evidence:
- Resource imports (
import-structure,import-template,import-adt,import-fragment): read back the updated resource withldev resource structure/template/adt/ldev resource export-*/ldev portal inventory ... --json. - Deploy/runtime changes (modules, themes, startup/runtime faults): use
ldev logs diagnose --since 5m --json. - Structured content or site page mutations: prefer OAuth-backed Headless APIs plus read-back before browser checks; use browser automation only when no stable headless mutation path exists for the target runtime.
- Resource imports (
- When the change affects rendered pages or UI, verify with browser automation after the runtime settles.
- If a command fails, diagnose first (
ldev logs diagnose --jsonorldev doctor --json) before retrying. - Never guess IDs, keys, or site names. Use
ldev portal inventory ...to resolve them. - Never assume the portal URL. Read
context.liferay.portalUrlfrom bootstrap output. - For
ldev-native, the recommended default for any task that mutates code/resources/runtime is: isolated worktree setup and root lock → Red reproduction in the worktree runtime → import/deploy verification with runtime evidence → Green visual validation in that same worktree runtime. Do not reproduce first in the primary checkout. For single-field config updates, copy fixes, or isolated template tweaks where the developer has explicitly named the file and change, proceeding in the current checkout without a worktree is acceptable. - Safety checks that apply to every task regardless of scope:
--check-onlybefore supported resource imports, read-after-write verification after mutations, ID and URL resolution vialdev portal inventory(never guess), and diagnosis before speculative fixes. These are not negotiable. Workflow steps (worktree isolation, browser validation) are the recommended default; skip them only when the developer has explicitly scoped a single-file change with no runtime resource mutations.
ldev Command Resolution
When instructions say ldev ..., resolve the CLI in this order:
- Try
ldevdirectly. - If
ldevis not available inPATH, runnpx @mordonezdev/ldev .... - On Windows PowerShell, if
npxis blocked by script execution policy, usenpx.cmd @mordonezdev/ldev ....
For agent work, treat npx.cmd @mordonezdev/ldev as the Windows-safe fallback. Do not stop on CommandNotFound for ldev until this fallback has been tried.
PowerShell ldev Invocation
On PowerShell, never build ldev commands as strings and never use Invoke-Expression for ldev. Pass arguments as an array so URLs, ?, &, quotes, and flags are preserved exactly:
$ldev = if (Get-Command ldev -ErrorAction SilentlyContinue) { 'ldev' } else { 'npx.cmd' }
$args = @('portal', 'inventory', 'page', '--url', $url, '--json')
$json = if ($ldev -eq 'ldev') { & ldev @args } else { & npx.cmd '@mordonezdev/ldev' @args }
$data = $json | ConvertFrom-JsonOn Windows Git Bash, protect Liferay friendly URLs such as /estudis with MSYS_NO_PATHCONV=1 or use PowerShell arrays. Do not pass rewritten C:/Program Files/Git/<site> values to --site.
Optional Shell Helpers
jqis not installed by default on every machine. Check withjq --version.- Install when needed:
- Windows:
winget install jqlang.jq - macOS:
brew install jq - Linux (Debian/Ubuntu):
sudo apt install jq
- Windows:
- In reusable agent docs, prefer direct JSON parsing by the agent or shell-native parsing (
ConvertFrom-Jsonin PowerShell) instead of assumingjqexists.
Default Operating Rules
- Use
ldevas the official entrypoint. Do not fall back to legacy wrappers or ad hoc project scripts when anldevcommand already exists. - Before using a
git,blade, or ad hoc shell command to accomplish something, checkldev --helpto verify noldevequivalent exists. - If an
ldev-nativetask needs isolated runtime state or a confirmed edit boundary, useisolating-worktreesfor the canonical setup, recovery, and cleanup flow. Default:ldev worktree setup --name <worktree-name> --with-env --stop-main-for-clone(main stays stopped). Add--restart-main-after-cloneonly if the user explicitly asks for main running alongside the worktree. - If the user asks for a vanilla sandbox, clean sandbox, or fresh Liferay sandbox, do not use
isolating-worktreesand do not clone the current repository into a worktree. Create a freshldevproject withldev project init, lock that root, and require an activation key beforeldev start. - If the current session is already inside a worktree, ask whether the user wants to keep working in that same worktree before creating another one. Do not silently switch away from the active worktree.
- Never use
git worktree adddirectly.git worktree addalone is incomplete and unsafe for this workflow. - After creating an isolated worktree, confirm the editing root with
git rev-parse --show-topleveland treat that root as an active edit boundary for the whole task. - Use
--cache=60for read-only bootstrap intents. Omit it only when the task explicitly requires fresh runtime or portal state. - Prefer the task-shaped public contract first:
ldev ai bootstrap --intent=discover --cache=60 --jsonfor read-only discoveryldev ai bootstrap --intent=develop --cache=60 --jsonbefore code/resource changesldev ai bootstrap --intent=deploy --jsonbefore deploy verificationldev context --jsonldev portal check --jsonldev portal inventory ... --jsonldev logs diagnose --jsonfor runtime/deploy diagnosisldev doctor --jsonwhen runtime or tool readiness matters
- For scripting and agents, prefer machine-readable output:
ldev ai bootstrap --intent=develop --cache=60 --jsonldev doctor --jsonldev context --jsonldev status --json
Branch and Worktree Lock
- Treat the current user-selected worktree as locked for the whole session.
- For detailed setup and recovery, use
isolating-worktrees. Keep this section focused on the always-on lock invariant only. - Do not switch to another worktree, checkout another branch, or run commands from another repo root unless the user explicitly asks for that switch in the current chat.
- Resolve and store one explicit
lockedRootat bootstrap from the current editor file path and terminal CWD. - If editor file path and terminal CWD point to different roots, stop and ask for explicit user confirmation before running any command.
- Prefix command sequences with an explicit shell-native directory change to the locked worktree root before running discovery, validation, import, deploy, or mutating commands that generate evidence (
cdin sh/bash/zsh/fish on Linux/macOS,Set-Locationin PowerShell on Windows). - Before reporting any import/deploy/edit as successful, verify in the same locked worktree runtime context (
ldev status --jsonand read-after-write evidence). - If context appears to point at a different worktree than the locked one, stop and ask for confirmation instead of continuing.
Project-Specific Knowledge
ldev installs reusable skills, not project-specific know-how.
Keep project-owned knowledge in project files, not in vendor-managed skills.
Recommended locations:
CLAUDE.mdfor Claude-specific routing and instructionsdocs/ai/project-context.mdfor maintainable long-form project context- extra skills under
.agents/skills/project-*for project-owned workflows
Read order:
AGENTS.mdCLAUDE.mddocs/ai/project-context.mdif it existsdocs/ai/project-learnings.mdif it exists- All files under
.workspace-rules/if that directory exists - task-specific skills under
.agents/skills/
Installed Skills
Use these as the standard reusable entrypoints when the task needs a deeper playbook:
routing-liferay-work: router for technical Liferay work.developing-liferay: implementation guidance for code, themes, content resources and fragments.isolating-worktrees: isolatedldev-nativeworktree setup, edit-root lock, recovery and cleanup.deploying-liferay: build, deploy and runtime verification flow.troubleshooting-liferay: diagnosis and recovery flow.runtime-change-workflow: canonical Red -> Green gates for mutating work.portal-resource-workflow: canonical workflow for structures, templates, ADTs and fragments.migrating-journal-structures: safe Journal migration playbook.automating-browser-tests: Playwright browser checks, visual evidence and page-editor workflows.capturing-session-knowledge: end-of-session knowledge distillation todocs/ai/project-learnings.md.
Validation
After installing or updating vendor skills:
- Review
.agents/skills/. - Update
CLAUDE.mdand adddocs/ai/project-context.mdonly if the project will maintain it. - Add any project-owned skills with the
project-prefix.