Imported from triphopp/bloomberg-terminal (
AGENTS.md). Install upstream withnpx skills add triphopp/bloomberg-terminal. Copyright stays with the author.
Bloomberg Terminal — Codex Instructions
Start every session by reading
memory/project_summary.mdIt contains the full picture: features, architecture, all key files, env vars, run commands, and known issues.
Quick reference
# Backend (Terminal 1) — macOS/Linux
cd backend
# env vars are in backend/.env — loaded automatically by python-dotenv
python -m uvicorn main:app --port 8000 --reload
# Backend (Terminal 1) — Windows PowerShell
cd backend
python -m uvicorn main:app --port 8000 --reload
# Frontend (Terminal 2)
npm run dev # → http://localhost:3000
Rules
- Never fetch Yahoo Finance directly from Next.js — always go through the Python backend
- Never reintroduce
@upstash/redis,yahoo-finance2, or any top-level scheduler singleton - Backend is modular:
main.py(app init) +config.py+db.py+routers/*.py - State lives in Jotai atoms (
components/bloomberg/atoms/index.ts) + React Query for server data
Memory Maintenance — What to Update After Each Change
| Changed | อัปเดตไฟล์เหล่านี้ |
|---|---|
| เพิ่ม router ใหม่ | project_summary.md (routers table) + reference/api-endpoints.md + reference/architecture.md |
| เพิ่ม endpoint ใหม่ | reference/api-endpoints.md + reference/data-shapes.md (ถ้า shape ใหม่) |
| เปลี่ยน response shape | reference/data-shapes.md ⚠️ อย่าลืม — frontend hardcode field names |
| เพิ่ม view ใหม่ | project_summary.md (views table) + AGENTS.md (views table) + reference/frontend-structure.md |
| เพิ่ม component / hook | reference/frontend-structure.md (exports table) |
| เพิ่ม TypeScript interface | reference/data-shapes.md + reference/frontend-structure.md (exports) |
| เพิ่ม env var | project_summary.md (env vars) + reference/gotchas.md (env var → feature map) |
| เพิ่ม DB table | project_summary.md (SQLite schema) + reference/data-shapes.md |
| แก้ bug ที่เป็น pattern | reference/gotchas.md (เพิ่ม error + fix) |
| เพิ่ม analytics module | reference/architecture.md (analytics folder section) |
Before investigating a bug: อ่าน reference/gotchas.md ก่อน — อาจเคยเจอแล้ว
Pattern Cookbook
Add a new backend endpoint
- Create/edit
backend/routers/X.py— definerouter = APIRouter() - Mount in
backend/main.py—app.include_router(x_router, tags=["X"]) - Create Next.js proxy
app/api/X/route.ts— fetch${PYTHON_API}/api/X - Update
memory/reference/api-endpoints.md+memory/project_summary.mdrouters table
Add a new frontend view
atoms/index.ts— add string literal to view atom unionhooks/useTerminalUI.ts— add keyboard handler caselayout/bloomberg-terminal.tsx— add{currentView === "X" && <XView />}blocklayout/terminal-header.tsx— add nav button- Update
memory/reference/frontend-structure.md+memory/project_summary.mdviews table
Add a new tab inside a tabbed view (credit-view, portfolio, …)
- Create
views/X-tab.tsx— component withh-full flex flex-col overflow-hiddenroot - Import + add to tab array in parent view
- Wire
Alt+Nshortcut interminal-layout.tsxif needed
Add a new portfolio tab
- Create
views/portfolio/tabs/XTab.tsx - Add to
tabListarray inviews/portfolio/index.tsx - Types go in
portfolio/types.ts, constants inportfolio/constants.ts, helpers inportfolio/helpers.ts
localStorage persistence (React — correct pattern)
// READ in useState initializer (not useEffect — fires too late)
const [val, setVal] = useState<T>(() => {
if (typeof window === "undefined") return DEFAULT;
try {
const s = localStorage.getItem("key");
if (s) return JSON.parse(s) as T;
} catch { /* ignore */ }
return DEFAULT;
});
// WRITE in useEffect keyed on the value
useEffect(() => { localStorage.setItem("key", JSON.stringify(val)); }, [val]);
// Side-effects: call setVal directly in handlers — NOT through a state-watching effect
Never use useEffect([dense]) to reset cols — it fires on mount and overwrites loaded state.
Scrollable section inside fixed-height container
// Parent must be h-full flex flex-col
<div className="flex flex-col h-full">
<div className="shrink-0">header / tabs</div>
<div className="flex-1 overflow-y-auto">scrollable content</div>
</div>
Without h-full on root or shrink-0 on header, content gets clipped by parent overflow-hidden.
React Query data fetch (standard pattern)
const { data, isLoading, error } = useQuery({
queryKey: ["X", param],
queryFn: () => fetch(`/api/X?param=${param}`).then(r => r.json()),
staleTime: 60_000,
});
SQLite schema update
Add table in backend/db.py → init_db() function. Use IF NOT EXISTS. Run via get_db() context manager. Never alter production columns directly — add new columns with ALTER TABLE ... ADD COLUMN IF NOT EXISTS.
Caching in a new router
from cache import TTLCache
_cache = TTLCache()
@router.get("/api/X")
async def get_x():
cached = _cache.get("x")
if cached: return cached
data = await fetch_data()
_cache.set("x", data, ttl=300)
return data
Views (9 views, post-RMI removal 2026-05-24)
| Key | Button | View | Content |
|---|---|---|---|
1 |
MKT | market-view | Watchlist · Chart · Global indices ticker |
2 |
NEWS | news-view | Financial news · Facebook social feed · Polymarket column (right 256px) |
3 |
GMOV | market-movers | Global indices table · Heatmap treemap |
4 |
CLIP | clippings-view | Obsidian markdown notes · Ollama AI |
T |
TAIL | tail-risk-view | 6 risk dimensions (composite) + MACRO CONTEXT (not in composite): event strip FOMC/SEP/CPI/NFP/PCE/GDP + EVENT WINDOW tag on VIX signals, Fed rate/stance, 10Y−2Y/10Y−3M, regime, latest prints, event markers on 90D chart |
6 |
CRDT | credit-view | 4 tabs: overview, spreads, stress, consumer |
P |
PORT | portfolio-view | 5 top-level: PORTFOLIO (sub: POSITIONS·OPTIONS·TRADES·CASH) · ANALYTICS (sub: P&L·BACKTEST) · RISK · TOOLS (sub: THESES·IMPORT) · PAPER (sub: DASHBOARD·TRADE·POSITIONS·OPTIONS·HISTORY) |
C |
CRYP | crypto-view | 20 crypto coins · Chart |
E |
FX | fx-view | 20 FX pairs · Chart |
Removed: GVOL (fake Math.random() data), EQTY (duplicates MKT search), RMI (removed 2026-05-24)
Stock analysis (9 tabs: financials, options, etc.) still accessible from global search / heatmap click
MACRO 5 removed 2026-09-17 — US macro (Fed, curve, indicators, regime) + FOMC/release calendar moved into TAIL as context; COUNTRY (World Bank) and SIGNALS (country rotation / sector selection / allocation) tabs were deleted with it. Backend routers remain (/api/macro, /api/sovereign/*, /api/country-rotation, /api/sector, /api/allocation) — TAIL reads /api/macro in-process. Key 5 is free.
3 Mandatory Rules (ALL agents, every session)
Rule 1 — Plan created:
สร้าง memory/plans/<name>.md → เพิ่ม - [ ] **Feature** — desc (\plans/.md`)ในproject_summary.md→ เพิ่มในINDEX.md`
Rule 2 — Plan completed:
ย้ายไฟล์ → plans/completed/ → เปลี่ยน [ ] เป็น [x] done YYYY-MM-DD ใน project_summary.md → อัปเดต INDEX.md
Rule 3 — Bug risk spotted:
ไม่แก้ถ้าไม่ใช่ scope → สร้าง memory/reports/<topic>-risk-report.md พร้อม: ไฟล์, บรรทัด, พฤติกรรม, ความเสี่ยง, วิธี reproduce → เพิ่มใน gotchas.md ถ้าเป็น pattern
รายละเอียด format ทั้งหมด →
memory/AGENTS.mdSection 6b
Memory files (in this repo)
memory/
├── INDEX.md ← navigation map
├── AGENTS.md ← format rules (อ่านก่อนเขียนไฟล์ใดๆ ใน memory/)
├── project_summary.md ← slim core: stack, env vars, 26 routers, DB schema, 9 views, known issues
├── reference/
│ ├── architecture.md ← data flow, key files, 26 routers table
│ ├── api-endpoints.md ← all endpoints + caching strategy + Next.js proxy routes
│ ├── frontend-structure.md ← full component tree + key exports + keyboard shortcuts
│ ├── data-shapes.md ← API response shapes (avoid reading router files)
│ └── data-catalog.md ← 17 data categories available for analysis
├── plans/ ← feature plans (active + completed/)
└── sessions/ ← audit trail + reports
Before writing any file in memory/: read memory/AGENTS.md for format rules.