#!/usr/bin/env python3 # SecondBrain — (c) 2026 Atlas Corporation. All Rights Reserved. Proprietary; see LICENSE. """SecondBrain setup wizard — connect the apps that feed your brain. python3 setup.py interactive: pick apps, sign in, test, sync python3 setup.py sync re-sync every already-connected app (for cron/timer) python3 setup.py list show available connectors App credentials go into the encrypted vault (connectors/vault.py), never into brain.db. """ import sys, os sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from connectors import base, vault def _ask(field): import getpass label = f" {field.label}" + (f" [{field.default}]" if field.default else "") + ": " val = getpass.getpass(label) if field.secret else input(label) return (val or "").strip() or field.default def cmd_list(): base.load_all() print("\nAvailable connectors:") for c in base.REGISTRY.values(): print(f" • {c.name:26} {c.blurb}") def wizard(): base.load_all() conns = list(base.REGISTRY.values()) print("\n🧠 SecondBrain — connect your apps\n") for i, c in enumerate(conns, 1): print(f" {i}. {c.name} — {c.blurb}") print(" q. done") cfgs = vault.load() if os.path.exists(vault.VAULT) else {} while True: ch = input("\nConnect which? [number/q] ").strip().lower() if ch in ("q", ""): break try: c = conns[int(ch) - 1] except Exception: print(" ?"); continue inst = c() cfg = {f.key: _ask(f) for f in inst.fields} try: print(" testing…", inst.test(cfg)) except Exception as e: print(f" ✗ could not connect: {e}"); continue cfgs[c.id] = cfg vault.save(cfgs) print(f" ✓ {c.name} connected + saved to encrypted vault") if input(" sync now? [Y/n] ").strip().lower() in ("", "y"): try: n = inst.sync(cfg); print(f" … ingested {n} new chunks") except Exception as e: print(f" sync error: {e}") print("\nEmbedding new content (local)…") try: base._brain().embed(limit=20000) except Exception as e: print(f" embed skipped: {e}") print('Done. Ask your brain: python3 brain.py recall "…" --hybrid\n') def cmd_sync(): base.load_all() cfgs = vault.load() if not cfgs: print("no connectors configured — run `python3 setup.py` first"); return for cid, cfg in cfgs.items(): c = base.REGISTRY.get(cid) if not c: print(f"[{cid}] unknown connector, skipped"); continue try: n = c().sync(cfg); print(f"[{cid}] +{n} chunks") except Exception as e: print(f"[{cid}] error: {e}") base._brain().embed(limit=50000) if __name__ == "__main__": arg = sys.argv[1] if len(sys.argv) > 1 else "" {"sync": cmd_sync, "list": cmd_list}.get(arg, wizard)()