Keep OpenHands working until Ultracite passes
OpenHands puts the full root AGENTS.md into the agent’s initial system prompt. Ultracite doesn’t write an OpenHands hook, but OpenHands documents a Stop hook for this job: when the agent tries to finish, the hook runs your linter and keeps the agent working until it passes.
OpenHands by All Hands AIChecked against OpenHands 1.26.0
# Ultracite Code Standards
This project uses **Ultracite**, a zero-config preset that enforces strict code quality standards through automated formatting and linting.
## Quick Reference
- **Format code**: `npx ultracite fix`
- **Check for issues**: `npx ultracite check`
- **Diagnose setup**: `npx ultracite doctor`
Oxlint + Oxfmt (the underlying engine) provides robust linting and formatting. Most issues are automatically fixable.
…- 1
AGENTS.mdUltraciteFrom the working directory, and from the Git repo root if that’s different. Its full content goes into the initial system prompt. - 2
CLAUDE.md, GEMINI.mdAlso loaded as repository context, along withAGENT.mdand.cursorrules. - 3
packages/*/AGENTS.mdA nested file becomes a path rule, injected the first time the agent reads, edits or creates a file under that directory. - 4
.agents/skills/Project skills. They win over the legacy.openhands/skills/and.openhands/microagents/when names clash.
How OpenHands reads the rules
OpenHands treats the root AGENTS.md as always-on repository context and nested AGENTS.md files as rules for their own directory. Skills come on top, from .agents/skills/ and the legacy .openhands/ folders.
- Working directory first
- Started in a subdirectory, OpenHands also checks the Git repo root, but a file in the working directory wins over the root’s file of the same kind.
- Keep it short
- Always-on content takes up context from the first message, so OpenHands suggests a concise
AGENTS.md. Ultracite’s rules are about 120 lines. - Setup script
.openhands/setup.shruns every time OpenHands starts work on the repo. Install dependencies there soultraciteis ready.- Hooks file
.openhands/hooks.json, committed to the repo. Hooks are active the next time OpenHands works on it.- Check it
- In the CLI,
/skillslists the loaded skills, hooks and MCP servers. In the Cloud, hook events show in the conversation log. - Symlinks
- A
CLAUDE.mdsymlinked toAGENTS.mdis loaded once, not twice.
A Stop hook that waits for a clean check
OpenHands hooks live in .openhands/hooks.json and work in the Cloud, the CLI and the local GUI. A PostToolUse hook can’t block there, so OpenHands’ own lint example uses a Stop hook; the snippets are that example with ultracite check swapped in. Ultracite doesn’t write them for you.
#!/bin/bash
# Stop hook: Don't let the agent stop if Ultracite finds problems
cd "$OPENHANDS_PROJECT_DIR"
if ! npx ultracite check 2>&1; then
echo '{"decision": "deny", "reason": "Ultracite found problems. Please fix them before finishing."}'
exit 2
fi
exit 0{
"stop": [
{
"matcher": "*",
"hooks": [
{
"command": ".openhands/hooks/lint_check.sh",
"timeout": 120
}
]
}
]
}- 01The agent edits files in its sandbox, with
AGENTS.mdin its system prompt. - 02When it tries to finish, OpenHands runs the Stop hook, which runs
npx ultracite check. - 03If the check fails, the hook prints a
denydecision and exits 2, and the agent keeps working. - 04Once the check passes, the hook exits 0 and the agent finishes. Make the script executable with
chmod +x.
Worth knowing about OpenHands
Nested files become path rules
A
packages/api/AGENTS.mdisn’t loaded up front. OpenHands turns it into a path rule and injects it once, the first time the agent reads, edits or creates a file underpackages/api/, so a package’s notes cost nothing until they’re needed.Headless runs approve everything
openhands --headless -t "…"runs without the terminal UI, for scripts and CI. It always runs inalways-approvemode, which can’t be changed, and--jsonstreams every event as JSON Lines you can parse.Issues and pull requests on GitHub
With OpenHands Cloud installed on a repository, label an issue
openhandsor start a comment with@openhands, and it opens a pull request when it’s done. Mention@openhandson a pull request to ask for updates.The Ultracite skill
OpenHands loads project skills from
.agents/skills/, whereinitinstalls the Ultracite skill, and from the legacy.openhands/skills/, where it also goes when the project has an.openhandsfolder. When both copies exist, the.agents/skills/one wins. Start a new conversation after adding it.
OpenHands questions, answered
- Does OpenHands read AGENTS.md?
- Yes. The root
AGENTS.mdis always loaded, in full, into the agent’s initial system prompt. OpenHands also recognizesAGENT.md,CLAUDE.md,GEMINI.mdand.cursorrulesas repository context. - How do I make OpenHands run the linter?
- The rules tell it to run
npx ultracite fixandnpx ultracite check. To enforce that, add a Stop hook that runsultracite checkand exits 2 when it fails, so OpenHands can’t finish until the check passes. - Will Ultracite’s Claude Code hook run in OpenHands?
- No. OpenHands reads hooks from
.openhands/hooks.json, not.claude/settings.json. Its format accepts Claude Code’s, but its tools have different names, such asterminalrather thanBash. - Why a Stop hook instead of PostToolUse?
- In OpenHands,
PostToolUsehooks can’t block, so they can’t send the agent back to work. AStophook can: exit code 2, or adenydecision, keeps the agent going. - What happened to microagents and repo.md?
- Microagents are now skills.
.openhands/microagents/still loads, but OpenHands recommendsAGENTS.mdfor repository-wide guidance and.agents/skills/for skills. - I use .openhands/pre-commit.sh. Should I keep it?
- OpenHands suggests moving checks from
.openhands/pre-commit.shinto a Stop hook, so the quality gate applies to its current agent-server-backed flows.
Keep going
- AgentDevinCognition’s autonomous coding agent, in cloud sessions, a CLI and a desktop app.
- AgentJulesGoogle’s asynchronous agent that works on your repo in a cloud VM and opens pull requests.
- AgentOnaBackground coding agents in cloud dev environments, formerly Gitpod and now part of OpenAI.
- DocsAgent rulesWhat
initwrites for every agent, and how to keep it current.
Ship less slop
One command sets up your linter, formatter, editor and agents. Works with Oxlint, Biome and ESLint.