Krohnos
Português

X knowledge agent

It turns the posts you saved on X into short knowledge recipes.

Personal use: it reads your own account, through your own session, in read-only mode.

What it is

It turns the posts you saved (bookmarks) on X into short knowledge recipes. Personal use: it reads your own account, through your own session, in read-only mode.

No password and no paid API: the agent never logs in, it uses the session you already have open in the browser. Each step is idempotent: a post already seen is not collected again and a recipe already written does not call the LLM again.

How it works

Flow of the X knowledge agentFive steps in sequence: saved posts on X, collection, extraction, recipe and use.1Saved posts on Xyour bookmarks, your account2Collectionheadless browser, read-only3Extractionthe post is data, text-only LLM4Recipevalidated, status curta5Uselibrary or issue text

Flow of the X knowledge agent

  1. Saved posts on X: the bookmarks of your account.
  2. Collection (coletar): headless browser, your session cookies, one collection per day, read-only. It writes <saida>/AAAA-MM-DD.jsonl and vistos.json (ids already collected); it writes ERRO if the session drops.
  3. Extraction (extrair): the post becomes data inside a block with a random delimiter; the LLM (claude -p) runs with no tools, no MCP servers and no user settings.
  4. Recipe: validated (frontmatter, size, no URL outside the post links, no dangerous command). With destino = "biblioteca" it goes to <saida>/receitas/<tema>/<id>-<titulo>.md (status curta); with "issue", to <saida>/issues/<id>-<titulo>.md.
  5. Use: the recipe enters the reference library, or becomes issue text, and is applied to real work.

Install

Get the package: it is the hub/x_salvos/ module of the Krohnos repository (https://github.com/BRK13/krohnos). Clone it and run every command on this page from its root:

bash
git clone https://github.com/BRK13/krohnos.git
cd krohnos
  • Python 3.11 or newer and an installed Chrome or Chromium.
  • Only playwright; the browser is the system one, pointed to by the chrome key:
  • For extrair: the claude CLI installed and signed in (it runs as claude -p --tools "" --strict-mcp-config --setting-sources "": text only, no tools, no MCP servers, no user or project settings or hooks), or your own executar_llm(prompt) function if you call the module from Python.
bash
pip install playwright

Export the cookies (next section) and create the x_salvos.toml (Configuration section). Test by hand, first the collection and then the extraction:

bash
python3 -m hub.x_salvos coletar --config x_salvos.toml
python3 -m hub.x_salvos extrair --config x_salvos.toml

To run every day, schedule this in the system cron (--jitter waits 0 to jitter_max_s before starting; by hand, run without it):

bash
python3 -m hub.x_salvos coletar --jitter --config x_salvos.toml

The commands are the ones in the module README, hub/x_salvos/README.md.

How to export the cookies

The agent never logs in: it uses the session you already have open in the browser. The session is yours, the password never enters, and there is no paid API.

  • Sign in to X in the browser, with your own account.
  • With a cookie-export extension, or through DevTools (Application, Cookies, https://x.com), copy only the value of auth_token, ct0 and twid.
  • Save a JSON with just those three keys:
json
{"auth_token": "...", "ct0": "...", "twid": "..."}
  • chmod 600 on the file. A more open file is fixed and reported, and the value never appears in the log.
  • A file with a password, username or any login credential is refused.
bash
chmod 600 ~/.config/x-salvos/cookies.json

When the session expires, the collection writes ERRO in the output folder and stops (exit code 2): export new cookies.

Configuration

File x_salvos.toml. Precedence: defaults, then file, then environment variables. An unknown key is an error. All the keys:

toml
cookies = "~/.config/x-salvos/cookies.json"   # JSON with auth_token, ct0, twid (chmod 600)
cookies_origem = ""                           # optional: file or folder where the cookies arrive from another machine
saida = "~/x-salvos"                          # jsonl, vistos.json, ERRO and recipes
temas = ["seo", "automacao"]                  # optional: a recipe outside the themes is flagged, never discarded
destino = "biblioteca"                        # "biblioteca" or "issue"
max_itens = 150                               # items per run (maximum 500)
max_paginas = 40                              # scrolls per run
limite_taxa_s = 1.5                           # minimum interval between navigations, in seconds
jitter_max_s = 1200                           # with --jitter: waits 0 to this value before starting
chrome = "/usr/bin/google-chrome"
trava = "~/x-salvos/.trava"                   # flock file against two collections; default <saida>/.trava
Keys of x_salvos.toml
KeyWhat it does
cookiesJSON with auth_token, ct0, twid (chmod 600)
cookies_origemOptional: file or folder where the cookies arrive from another machine (in a folder: the same file name as cookies, or x-cookies.json)
saidaOutput folder: jsonl, vistos.json, ERRO and recipes
temasOptional: a recipe outside the themes is flagged, never discarded
destino"biblioteca" writes to <saida>/receitas/<tema>/<id>-<titulo>.md (status curta); "issue" writes to <saida>/issues/<id>-<titulo>.md
max_itensLimit: items per run, maximum 500
max_paginasLimit: scrolls per run
limite_taxa_sLimit: minimum interval between navigations, in seconds
jitter_max_sWith --jitter: waits 0 to this value before starting
chromePath of the system Chrome or Chromium
travaLock file against two collections at once; default <saida>/.trava

Environment variables:

text
KROHNOS_X_SALVOS_CONFIG, KROHNOS_X_SALVOS_COOKIES, KROHNOS_X_SALVOS_COOKIES_ORIGEM, KROHNOS_X_SALVOS_SAIDA, KROHNOS_X_SALVOS_TEMAS, KROHNOS_X_SALVOS_DESTINO, X_MAX_ITENS, KROHNOS_X_SALVOS_MAX_PAGINAS, KROHNOS_X_SALVOS_LIMITE_TAXA_S, KROHNOS_X_SALVOS_JITTER_MAX_S, KROHNOS_X_SALVOS_CHROME, KROHNOS_X_SALVOS_TRAVA

The 6 guardrails and the test that proves each one

All of them are in code (guardrails.py) and each one fails if the code is removed. The tests live in tests/test_x_salvos_guardrails.py, tests/test_x_salvos_extrair.py and tests/test_x_salvos_config.py.

Guardrails and tests
GuardrailWhat it guaranteesTest that proves it
1. Read-onlyWrite methods and write endpoints (even over GET) are aborted and logged without a body. The only click allowed is expanding replies; like, repost and follow are refused. An unreadable URL, encoding tricks or a subdomain open no gap: failure closes. The lock sits in the browser context, including in --refazer-fio. Service Workers are blocked, so nothing slips past the lock.tests/test_x_salvos_guardrails.py: TestSomenteLeitura.test_metodos_de_escrita_bloqueados, test_endpoints_de_escrita_bloqueados_mesmo_em_get, test_instalar_aborta_escrita_e_registra_sem_corpo, test_clique_de_acao_recusado, test_url_ilegivel_aborta_fail_closed, test_brechas_de_codificacao_e_subdominio, test_abrir_instala_a_trava_no_contexto, test_refazer_fio_abre_pelo_abrir
2. The session is yoursOnly auth_token, ct0 and twid; a login credential is refused. There is no login flow and the collection never navigates to the login screen. Cookies arriving from another machine (cookies_origem) are copied only if newer, with chmod 600, with no value in the log.tests/test_x_salvos_guardrails.py: TestSessaoDoUsuario.test_cookies_so_os_tres, test_rejeita_credencial_de_login, test_fonte_sem_fluxo_de_login, test_nao_navega_para_login, TestCookiesOrigem
3. Rate limit, ceiling and stop if the session dropsMinimum interval between navigations (limite_taxa_s) and a ceiling on scrolls and items per run. If the session drops, the collection detects it from the URL, writes ERRO in the output folder and stops without retrying (exit code 2).tests/test_x_salvos_guardrails.py: TestLimiteETeto.test_intervalo_minimo_entre_navegacoes, test_ir_respeita_a_taxa, test_teto_de_rolagens, test_teto_de_itens, test_sessao_caiu_por_url, TestParada
4. Post content is data, not instructionThe post text sits inside a block with a random delimiter; a forged delimiter is neutralized. Extraction runs claude -p text-only: no tools, no MCP servers, no user or project settings, and without skipping permissions. The answer is validated: a dangerous command, a URL outside the post links, or an invalid format or size rejects that recipe and the rest goes on.tests/test_x_salvos_extrair.py: TestPrompt, TestValidacao, TestDestino.test_resposta_perigosa_nao_grava_e_pipeline_segue, TestDestino.test_padrao_nao_usa_bypass
5. SecretsA cookie value is masked in every log and in the ERRO file. Cookies are written with chmod 600, atomically; a more open permission is fixed and reported, without showing the value.tests/test_x_salvos_guardrails.py: TestSegredos.test_mascarar, test_log_nunca_mostra_valor, test_erro_gravado_vai_mascarado, test_gravar_cookies_600_atomico, test_permissao_mais_aberta_e_corrigida_sem_valor, test_ler_cookies_corrige_permissao
6. Terms of use: personal useReads only your own saved posts; public search is outside this agent. No mass scraping and nothing written to X. At most 500 items per collection (also with --forcar, which is for the first load or a fix), one collection per day and one at a time. The notice is printed by --help and on the first run. Complying with the terms of use of X is the user's responsibility.tests/test_x_salvos_guardrails.py: TestTermos.test_aviso_tem_o_essencial, test_ajuda_e_primeira_rodada_imprimem_aviso, test_teto_500, test_uma_coleta_por_dia, TestColetorPuro.test_trava_impede_segunda_coleta

An invalid destination or ceiling is refused before collecting (tests/test_x_salvos_config.py). Run the proof:

bash
python3 -m unittest tests.test_x_salvos_config tests.test_x_salvos_guardrails tests.test_x_salvos_extrair

Terms notice

Warning: This tool reads only the saved posts of your own account, read-only; public search is outside this agent. No mass scraping: at most 500 items per collection and one collection per day (--forcar is for the first load or a fix and also respects the ceiling). Personal use. You are responsible for complying with the terms of use of X.