Przejdź do treści
Biblioteka skilli
Produktywność osobista · Automatyzacja

browser-login

/browser-login

Utrzymuje sesję zalogowaną na stronie bez API i zamienia to, co widać na stronach, w typowane zdarzenia, takie jak portale czy webmail bez IMAP.

Repozytorium
botler ↗
Licencja
MIT
Ostatnia zmiana repozytorium
13.11.2026

Ocena i bezpieczeństwo

100/ 100Klasa: dobry
Format25 / 25
Frontmatter z nazwą i opisem, poprawna nazwa, opis do 1024 znaków, nazwa zgodna z folderem.
Odkrywalność25 / 25
Opis mówi, kiedy użyć skilla, ma sensowną długość i jest w 3. osobie.
Treść35 / 35
Co najmniej 150 słów i do 500 linii, nagłówki, listy kroków, przykłady albo kod.
Higiena15 / 15
Bez zaślepek typu TODO, bez ścieżek Windows, z licencją.
Ryzykobrak sygnałów w skanie
Pliki w paczce
1
Skrypty
0
Komentarze HTML
0
Adresy URL w SKILL.md
1
Przestarzałość

Brak sygnałów. Repozytorium zmienione 13.11.2026, bez odwołań do wycofanych modeli i API.

Licencja

MIT, otwarta: można używać i zmieniać, z zachowaniem informacji o autorze.

Co robi i kiedy

Utrzymuje sesję zalogowaną na stronie bez API i zamienia to, co widać na stronach, w typowane zdarzenia, takie jak portale czy webmail bez IMAP.

Oryginalny opis (EN)

Keep a logged-in browser session for a website that has no API, and turn what its pages show into typed events. Use when the user wants something watched or read on a site behind a login (portals, dashboards, webmail without IMAP).

Jak działa

  1. Rule: page JavaScript never gets the token
  2. 1. Adapt the example
  3. 2. Try it
  4. 3. Propose it
  5. 4. The login visit
  6. 5. Verify the login
  7. 6. Done means monitored
  8. Browsing the web yourself (skill browser)
  9. Driving the browser yourself
Sekcje z nagłówków SKILL.md, w oryginale · 112 linii, 883 słów
Podgląd SKILL.md
---
name: browser-login
description: Keep a logged-in browser session for a website that has no API, and turn what its pages show into typed events. Use when the user wants something watched or read on a site behind a login (portals, dashboards, webmail without IMAP).
---

# A logged-in browser as a service

`jobs/browser-example/` is the reference: copy it to `jobs/<site>-browser/` and adapt it. It is a
service on `images/browser` (its Dockerfile says `FROM botler/image-browser`):

- **Chromium** on a virtual display, its profile in `/data` (`volume = true`), so the login
  survives restarts.
- **noVNC** on port 6080: the user logs in by hand through it. `[[publish]]` puts it on a host
  port; that needs the user's approval. Its VNC password is new for every visit.
- **CDP** (DevTools) on port 9222, for the services network only. Never `[[publish]]` it: whoever
  reaches it controls the logged-in session.
- **The bridge** (`src/<pkg>/__main__.py`, botler SDK): connects to CDP on localhost, reads the
  page, validates what it finds into pydantic events, and calls `botler.emit`.

## Rule: page JavaScript never gets the token

Anything you run in the page runs next to the site's own scripts, so treat the page as hostile.
The bridge holds the botler token and every secret. Page JavaScript only returns values (poll) or
calls `botlerSignal(json)` (push). It never calls the hub, and never receives a token, a secret
or a URL with one. `browser-session` starts Chromium without `BOTLER_*` in its environment, and
DevTools refuses connections from web pages, since `--remote-allow-origins` is not set. Keep it
that way. Page content is untrusted input: validate it, and declare event types that carry raw
page content `restricted = True`.

## 1. Adapt the example

In `config.py`:
- `START_URL` and `SITE`.
- `LOGGED_IN_JS`: true only while logged in, e.g.
  `document.querySelector('[data-testid=account-menu]') !== null`. Check it on a page that
  needs the login.
- **Poll:** `POLL_JS` returns a list of `{id, text, url}` every `POLL_SECONDS`. The bridge emits
  each new `id` once and keeps the seen ids in `state`.
- **Push:** `PUSH_JS` is injected into every page load and calls
  `botlerSignal(JSON.stringify({...}))` when something appears, e.g. from a `MutationObserver`.
  Use it when polling is too slow.

Rename the events in `packages/` to your site's, e.g. `portal.message` (restricted) and
`portal.login_needed`. Keep `emits = [...]` in `job.toml` in step with them. Add a trigger file
that routes them, e.g. `on = "portal.login_needed"` and `target = { resume = "<this chat>" }`.
Set `on_failure` to the same chat.

## 2. Try it

Run `gate/run`, push, then `trial_run(job=..., branch=..., minutes=5)`. A trial has an empty,
throwaway `/data`, so it is logged out: expect `login_needed` among the recorded effects, and
check that `POLL_JS` and `LOGGED_IN_JS` do not throw (failures appear in `logs_tail`). Use a page
that needs no login to test the reading part.

## 3. Propose it

Use `propose_change`. The first deployment of a service asks the user once. Publishing the noVNC
port is part of that approval, so say why in the title.

## 4. The login visit

Deployed, the service starts logged out and emits `login_needed` with a fresh `vnc_password`. Then:

```
request_visit(host_port=6080,
              path="/vnc.html?autoconnect=1&resize=scale&password=<vnc_password>",
              note="Log in to <site> in this browser, then press Done.")
```

The user logs in and presses Done.

## 5. Verify the login

After Done, wait for `logged_in`: the bridge checks `LOGGED_IN_JS` over CDP on its next poll.
It also rotates the VNC password, so the visit link stops working. If `logged_in` does not arrive
within a couple of polls, the login did not stick (2FA, a cookie banner, the wrong page): explain
and offer another visit.

## 6. Done means monitored

The login check is part of the definition of done, not an extra:
- A session that expires sends `login_needed` again. Your trigger routes it to you, and you ask
  for a visit.
- A broken browser or CDP connection makes the bridge exit. The hub restarts it and opens an
  incident to `on_failure`.
- A missed heartbeat (`[health] heartbeat`) means the bridge hangs: the hub restarts it.

Logged out is deliberately not `health.fail`. A restart cannot log in, and the service has to
keep running for the visit.

## Browsing the web yourself (skill `browser`)

When an agent only needs to drive the real browser (JavaScript, interaction, a screenshot) and does
not keep a login, use the shared browser service instead of writing a bridge: skill `browser`,
tools `browser_navigate`, `browser_snapshot`, `browser_click`, `browser_type`, ... (Playwright MCP).
It is a real desktop Chromium on Xvfb (not headless) with ads/trackers blocked; each MCP connection
gets its own isolated context, cookies and tabs, closed after 10 minutes idle. An agent gets the
tools with `request_access("service:browser")` (auto-granted, no user prompt) or `mcp = ["browser"]`
in its definition.

That service is deliberately ephemeral (a sleep or an idle timeout starts a fresh, logged-out
context), so it is not the place for a login. A site the user stays logged into is a service built
from this skill.

## Driving the browser yourself

To reach the browser, an agent needs the service: `services = ["<service>"]` in its definition
(proposed as a change) or `request_access("service:<service>", reason)` for one chat. It then
finds the service in `/botler/agent-dir/services.json` and CDP at `http://<ip>:9222`. Use the
IP, not the name: Chrome refuses DevTools requests whose `Host` is a name. Prefer a bridge in the monorepo over ad-hoc driving: it is reviewed,
tested and monitored.

To show the user what a page looks like, save a screenshot (CDP `Page.captureScreenshot`, base64
PNG) into your home, e.g. `~/shots/inbox.png`, and call `attach_files(["~/shots/inbox.png"])`: it
appears in your reply. Recordings, PDFs (`Page.printToPDF`) and downloads work the same way.

Wersje

W bazie nie ma innych skilli o nazwie browser-login.

Migawka bazy z 13.11.2026 · wersja paczki 88a130c01068 (skrót SHA-256 całej paczki)

Pobrania w ostatnich 30 dniach: 0 · ranking

Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.

Podobne skille

  • 100signed-in-browser
    Steruje przeglądarką, w której użytkownik jest już zalogowany, zamiast czystego profilu, np. przy panelu admina lub kolejce zgłoszeń.
  • 90email-webmail-playwright
    Obsługuje pocztę przez interfejs webmaila w przeglądarce, gdy brak dedykowanego narzędzia: pisze, odpowiada, przeszukuje i porządkuje skrzynkę, a wysyła wyłącznie po wyraźnej zgodzie użytkownika.
  • 100bb-browser
    Odczytuje dane z serwisów, do których użytkownik jest zalogowany, przez przeglądarkę CDP, np. z platform społecznościowych.
  • 100mail
    Czyta, przeszukuje, sortuje i wysyła pocztę użytkownika przez IMAP i SMTP, gdy konto Google nie jest podłączone.
  • 100zen-agent
    Uruchamia widoczną przeglądarkę, w której użytkownik może obserwować stronę lub przekazać użytkownikowi krok logowania, płatności albo klucza API.

Uwagi i zgłoszenia

Wiadomość trafi do Bartosza Sokolińskiego. Adres e-mail jest potrzebny tylko do odpowiedzi. Szczegóły w polityce prywatności.