Repository navigation
Project Outcome Analysis
Project: browser-use, forked to swisherae/browser-use.
Assistant used: Claude Code in VS Code, reading the whole repository. See the AI Use Log for what it wrote versus what I wrote.
All line numbers below are from my fork at the commit linked in each section, and I can open any of these files on request.
Screenshot 1 — my fork's GitHub page, showing "forked from browser-use/browser-use":
Screenshot 2 — git remote -v and git log --oneline -5 in my local clone:
Screenshot 3 — my assistant listing this repository's real top-level directories:
1. Iteration with an agile approach (Unified Process). CLAUDE.md spells out the project's own iteration rule at line 110, under "Strategy For Making Changes": confirm the existing behavior with tests, write failing tests for the new behavior, implement, then run the whole tests/ci suite (65 test files) before touching docs. The architecture supports that pace, since browser_use/browser/watchdogs/ holds 15 separate watchdog files, so new browser behavior arrives as a new file rather than a rewrite of the core. Strong fit.
2. Work in teams to design software. Team design here happens through pull requests: .github/CONTRIBUTING.md points contributors at the issue tracker, and the lint.yml and test.yaml workflows run automatically on every pull request. I can show a real review thread: issue #5598 became PR #5599, which took 6 commits and 2 review comments from maintainer Magnus Müller before merging. Weak spot: I have not opened a pull request of my own yet, so I can show the process but not my own participation in it.
3. Analyze a software application problem with use cases. The repository ships no use-case documents, so I wrote three fully-dressed ones myself (Look Up Information Online, Submit Web Form, Collect Data From Website) against the real entry point, Agent.run() in browser_use/agent/service.py line 2503, with the individual steps mapping onto actions registered in browser_use/tools/service.py. I then ran all three against live websites to check each step, which turned up two places where my own text was wrong. Strong fit, but the artifacts are mine, not the project's.
4. Conceptual domain model with UML class diagram. I built one from the nouns in those use cases: 16 classes with associations, role names and multiplicities, with the source in docs/domain-model.md. Real code sits behind the concepts, such as EnhancedDOMTreeNode for a page element (browser_use/dom/views.py, line 379) and AgentHistory for a finished step (browser_use/agent/views.py, line 488). The interesting part is where they disagree: a Task is a real thing in the domain but is only a task: str argument in the code (service.py, line 138).
5. System Sequence Diagrams. One agent step is a clean sequence of messages: Agent.step() sends the page and history to the AI model, hands the decision to Tools.act(), which dispatches a ClickElementEvent (browser_use/tools/service.py, line 731), which DefaultActionWatchdog.on_ClickElementEvent receives (browser_use/browser/watchdogs/default_action_watchdog.py, line 337) and turns into a CDP command to Chrome. Each arrow is a real message, not a drawing convention. Strong fit.
6. Operation contracts. Every action in browser_use/tools/service.py takes a pydantic parameter model, whose validation acts as the precondition, and returns an ActionResult (browser_use/agent/views.py, line 307) carrying is_done, success, extracted_content and error, which acts as the postcondition. The contracts are therefore enforced by code but never written in prose, so the writing is my work.
7. Logical architectures and message passing. The system is layered and event-driven: Agent decides, Tools acts, BrowserSession owns a bubus event bus, and CDP carries JSON over a websocket to a separate Chrome process. The decoupling is real, since the code that wants a click (tools/service.py, line 731) never names the code that performs it (default_action_watchdog.py, line 337); they meet only through the event's name. Strong fit.
8. Software patterns, with code. BaseChatModel in browser_use/llm/base.py line 33 is a Protocol, implemented separately by browser_use/llm/openai/, anthropic/, google/, deepseek/ and others. Callers just invoke ainvoke(...) without knowing which provider answers, which is the Strategy pattern with runnable code. I exercised it myself by swapping providers three times while getting the project running.
9. Object design and GRASP. Agent is the Controller: it receives the task and coordinates everything without being the model or the browser. DomService (browser_use/dom/service.py, line 45) is the Information Expert for page structure, because it alone holds the raw DOM and accessibility data. The 15 watchdog files give Low Coupling and High Cohesion, since each handles one concern and can be removed without touching the others.
10. UML activity diagrams. The Agent.step() loop is a natural activity diagram: capture the page, ask the model, branch on whether the task is done, execute the actions, repeat. Nothing like it is drawn in the repository, so this is a diagram I would produce from code I have already traced. Fair fit, no artifact yet.
11. UML state diagrams. Weak fit. AgentState (browser_use/agent/views.py, line 251) records the agent's lifecycle as separate booleans, paused at line 266 and stopped at line 267, rather than one named state value. The real states (idle, running, paused, stopped) exist only as combinations of those flags, so I would have to formalize the machine myself, and arguing that the code should have an explicit state is the more honest exercise.
12. Basic design principles. Single Responsibility shows in the watchdog split, where SecurityWatchdog only checks addresses and DownloadsWatchdog only handles downloads. Dependency Inversion shows in Agent depending on the abstract BaseChatModel (llm/base.py, line 33) instead of a concrete provider class, which is exactly why I could switch from browser-use's service to DeepSeek to Gemini by changing one line.
13. Test-driven development. CLAUDE.md line 110 requires writing failing tests for a new design before implementing it, which is textbook TDD stated as project policy. The tests live in tests/ci (65 files) and the test.yaml and lint.yml workflows run them on every pull request. I ran a relevant subset myself while checking my use cases, and 139 tests passed. Strong fit.
14. GUI development using an IDE. Poor fit, and worth stating plainly. There is no GUI toolkit anywhere in the library: searching browser_use/ for gradio, tkinter, streamlit and textual returns nothing. The project drives other people's interfaces, real websites in a real Chrome window, through CDP, which is close to the opposite of building screens yourself. I cannot demonstrate this outcome from this project without bolting on an unrelated side project.
15. Software Architecture Document. Weak fit. No architecture document exists in the repository. The closest thing is the "High-Level Architecture" section of CLAUDE.md, a few paragraphs naming Agent, BrowserSession, Tools, DomService and the watchdogs, with no views, no diagrams and none of the structure a real SAD needs. The material to write one exists, so this is an authoring task rather than a discovery task, but the artifact is missing today.
16. Write and present orally. This one isn't tied to any file, since it measures my delivery rather than the project. What the project supplies is content I can defend live: the event flow in outcome 7, the Strategy pattern in outcome 8, and the GRASP assignments in outcome 9, each with a file I can open on screen. Neutral fit, since the project neither helps nor hinders it.
17. Misuse and abuse cases. Strong fit, with a real finding. browser_use/browser/watchdogs/security_watchdog.py defends one concrete abuse case, a page steering the agent to a domain the operator never approved, and it checks at three points: before navigation (line 35), after the page loads to catch redirects (line 50), and when a new tab appears. _is_url_allowed (line 176) and _is_ip_address (line 138) even catch disguised IP addresses in decimal, hex and octal forms. When I tested it live with allowed_domains=['example.com'], the blocked page began loading before the "before navigation" check ran, and the tab was then switched to about:blank, so the request still reached the blocked site. That gap is exactly what a misuse-case analysis is supposed to surface.