diff --git a/docs/modules/usage/customization/repository.md b/docs/modules/usage/customization/repository.md new file mode 100644 index 0000000000..5fe6d6b3ac --- /dev/null +++ b/docs/modules/usage/customization/repository.md @@ -0,0 +1,24 @@ +# Repository Customization + +You can customize how OpenHands works with your repository by creating a +`.openhands` directory at the root level. + +## Microagents +You can use microagents to extend the OpenHands prompts with information +about your project and how you want OpenHands to work. See +[Repository Microagents](../prompting/microagents-repo) for more information. + + +## Setup Script +You can add `.openhands/setup.sh`, which will be run every time OpenHands begins +working with your repository. This is a good place to install dependencies, set +environment variables, etc. + +For example: +```bash +#!/bin/bash +export MY_ENV_VAR="my value" +sudo apt-get update +sudo apt-get install -y lsof +cd frontend && npm install ; cd .. +``` diff --git a/docs/sidebars.ts b/docs/sidebars.ts index 3c72cef136..f41c65df50 100644 --- a/docs/sidebars.ts +++ b/docs/sidebars.ts @@ -50,6 +50,17 @@ const sidebars: SidebarsConfig = { }, ], }, + { + type: 'category', + label: 'Customization', + items: [ + { + type: 'doc', + label: 'Repository Customization', + id: 'usage/customization/repository', + }, + ], + }, { type: 'category', label: 'Usage Methods', diff --git a/openhands/runtime/base.py b/openhands/runtime/base.py index aa05b64622..26864cb467 100644 --- a/openhands/runtime/base.py +++ b/openhands/runtime/base.py @@ -362,12 +362,23 @@ class Runtime(FileEditRuntimeMixin): self.run_action(action) return dir_name + def maybe_run_setup_script(self): + """Run .openhands/setup.sh if it exists in the workspace or repository.""" + setup_script = '.openhands/setup.sh' + read_obs = self.read(FileReadAction(path=setup_script)) + if isinstance(read_obs, ErrorObservation): + return + + action = CmdRunAction(f'chmod +x {setup_script} && source {setup_script}') + obs = self.run_action(action) + if isinstance(obs, CmdOutputObservation) and obs.exit_code != 0: + self.log('error', f'Setup script failed: {obs.content}') + def get_microagents_from_selected_repo( self, selected_repository: str | None ) -> list[BaseMicroAgent]: """Load microagents from the selected repository. If selected_repository is None, load microagents from the current workspace. - This is the main entry point for loading microagents. """ diff --git a/openhands/server/session/agent_session.py b/openhands/server/session/agent_session.py index 470b2bf581..2e609eed28 100644 --- a/openhands/server/session/agent_session.py +++ b/openhands/server/session/agent_session.py @@ -282,6 +282,7 @@ class AgentSession: selected_repository, selected_branch, ) + await call_sync_from_async(self.runtime.maybe_run_setup_script) self.logger.debug( f'Runtime initialized with plugins: {[plugin.name for plugin in self.runtime.plugins]}'