<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Labs on LibreLeo: Financial Freedom for Globally Mobile Investors</title><link>https://libreleo.com/lab/</link><description>Tools, math, and lived experience for expats building wealth across borders. Passive portfolios and active income from a Dubai-based trader.</description><generator>Hugo -- gohugo.io</generator><language>en</language><copyright>Copyright © 2026 | All rights reserved</copyright><atom:link href="https://libreleo.com/lab/index.xml" rel="self" type="application/rss+xml"/><item><title>My Daemon Dashboard</title><link>https://libreleo.com/lab/daemon/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://libreleo.com/lab/daemon/</guid><description>Real-time view of my personal daemon API data</description><content:encoded><![CDATA[<p>I imagine a future where technology’s main purpose is to deepen human connection. Daemons act as live windows into what we’re doing and caring about, helping us instantly find and connect with people who share our interests. Here's my Daemon</p>
<div id="daemon-dashboard" class="daemon-container">
  
  <div id="loading-state" class="loading-state">
    <div class="loader"></div>
    <p>Establishing MCP connection...</p>
  </div>

  
  <div id="error-state" class="error-state" style="display: none;">
    <div class="error-icon">⚠️</div>
    <p id="error-message"></p>
    <button onclick="fetchDaemonData()" class="retry-btn">Retry Connection</button>
  </div>

  
  <div id="dashboard-content" style="display: none;">

    
    <div class="status-bar">
      <div class="status-left">
        <span class="daemon-label">DAEMON://CHRISWENK</span>
        <div class="connection-status">
          <span id="status-dot" class="status-dot"></span>
          <span id="status-text" class="status-text">CONNECTED</span>
        </div>
      </div>
      <div class="status-right">
        <span id="tool-count">0 endpoints</span>
        <span id="last-updated"></span>
        <span id="current-date"></span>
      </div>
    </div>

    
    <div class="about-header">
      <div class="card-header">
        <span class="card-icon">👤</span>
        <span class="card-title">ABOUT</span>
      </div>
      <div class="about-content">
        <p id="about-content">Loading...</p>
      </div>
    </div>

    
    <div class="dashboard-grid grid-2">
      
      <div class="dashboard-card">
        <div class="card-header">
          <span class="card-icon">📖</span>
          <span class="card-title">NARRATIVE</span>
        </div>
        <div class="card-content">
          <p id="narrative-content">Loading...</p>
        </div>
      </div>

      
      <div class="dashboard-card">
        <div class="card-header">
          <span class="card-icon">🎯</span>
          <span class="card-title">MISSION</span>
        </div>
        <div class="card-content">
          <p id="mission-content">Loading...</p>
        </div>
      </div>
    </div>

    
    <div class="dashboard-card telos-full-width">
      <div class="card-header">
        <span class="card-icon">🧭</span>
        <span class="card-title">TELOS FRAMEWORK</span>
      </div>
      <div class="card-content">
        <div id="telos-content"></div>
      </div>
    </div>

    
    <div class="dashboard-grid grid-4">
      
      <div class="dashboard-card">
        <div class="card-header">
          <span class="card-icon">📍</span>
          <span class="card-title">LOCATION</span>
        </div>
        <div class="card-content">
          <p id="location-content">Loading...</p>
        </div>
      </div>

      
      <div class="dashboard-card">
        <div class="card-header">
          <span class="card-icon">📚</span>
          <span class="card-title">BOOKS</span>
          <span id="books-count" class="item-count">0</span>
        </div>
        <div class="card-content">
          <div id="books-content"></div>
        </div>
      </div>

      
      <div class="dashboard-card">
        <div class="card-header">
          <span class="card-icon">🎬</span>
          <span class="card-title">MOVIES</span>
          <span id="movies-count" class="item-count">0</span>
        </div>
        <div class="card-content">
          <div id="movies-content"></div>
        </div>
      </div>

      
      
    </div>

    
    <div class="dashboard-grid grid-4">
      
      <div class="dashboard-card">
        <div class="card-header">
          <span class="card-icon">🔮</span>
          <span class="card-title">PREDICTIONS</span>
        </div>
        <div class="card-content">
          <div id="predictions-content"></div>
        </div>
      </div>

      
      <div class="dashboard-card">
        <div class="card-header">
          <span class="card-icon">⚙️</span>
          <span class="card-title">PREFERENCES</span>
        </div>
        <div class="card-content">
          <div id="preferences-content"></div>
        </div>
      </div>

      
      

      
      <div class="dashboard-card">
        <div class="card-header">
          <span class="card-icon">💼</span>
          <span class="card-title">PROJECTS</span>
        </div>
        <div class="card-content">
          <div id="projects-content"></div>
        </div>
      </div>
    </div>

    
    <div class="api-footer">
      <div class="api-card">
        <div class="api-header">
          <span class="card-icon">🖥️</span>
          <span class="card-title">API ACCESS</span>
        </div>
        <code class="api-url">mcp-daemon.chriswenk.workers.dev</code>
        <p class="api-desc">Connect your AI assistant directly • Public API • No authentication required</p>
        <a href="/daemon-api-public-access" class="api-docs-btn">View API Docs →</a>
      </div>
    </div>

  </div>
</div>

<style>
.daemon-container {
  max-width: 100%;
  margin: 0 auto;
  padding: 2rem 0;
  width: 100%;
}

 
.loading-state, .error-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 4rem 1rem;
  gap: 1rem;
}

.loader {
  width: 40px;
  height: 40px;
  border: 4px solid rgba(0, 0, 0, 0.1);
  border-top-color: var(--primary);
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

.error-icon {
  font-size: 3rem;
}

.retry-btn {
  padding: 0.75rem 1.5rem;
  background: var(--primary);
  color: white;
  border: none;
  border-radius: 0.5rem;
  cursor: pointer;
  font-family: monospace;
  font-size: 0.875rem;
}

.retry-btn:hover {
  opacity: 0.9;
}

 
.status-bar {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  padding: 1rem 1.5rem;
  background: rgba(0, 0, 0, 0.05);
  border-radius: 0.75rem;
  margin-bottom: 1.5rem;
  font-family: monospace;
  font-size: 0.875rem;
}

.status-left, .status-right {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.daemon-label {
  font-weight: bold;
  color: var(--primary);
}

.connection-status {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #10b981;
  animation: pulse 2s ease-in-out infinite;
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.5; }
}

 
.dashboard-grid {
  display: grid;
  gap: 1rem;
  margin-bottom: 1rem;
}

.grid-2 {
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}

.grid-3 {
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}

.grid-4 {
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}

 
.telos-full-width {
  width: 100%;
  margin-bottom: 1.5rem;
}

.telos-full-width .card-content {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 0.5rem;
  max-height: none;
}

 
.about-header {
  background: rgba(0, 0, 0, 0.02);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 0.75rem;
  padding: 1.5rem;
  margin-bottom: 1.5rem;
}

.about-content {
  margin-top: 1rem;
  line-height: 1.6;
}

.about-content p {
  margin: 0;
  opacity: 0.9;
}

 
.dashboard-card {
  background: rgba(0, 0, 0, 0.02);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 0.75rem;
  padding: 1.25rem;
  max-height: 300px;
  display: flex;
  flex-direction: column;
}

.card-header {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 1rem;
  font-family: monospace;
  font-size: 0.875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.card-icon {
  font-size: 1.25rem;
}

.card-title {
  flex: 1;
}

.item-count {
  font-size: 0.75rem;
  opacity: 0.6;
}

.card-content {
  flex: 1;
  overflow-y: auto;
  padding-right: 0.5rem;
}

.card-content p {
  margin: 0.5rem 0;
  line-height: 1.6;
}

.card-content .list-item {
  font-size: 0.875rem;
  line-height: 1.6;
  margin: 0.5rem 0 0.5rem 1.5rem;
  opacity: 0.8;
  position: relative;
}

.card-content .list-item::before {
  content: "•";
  position: absolute;
  left: -1rem;
  color: var(--primary);
  font-weight: bold;
}

.card-content .list-item strong {
  font-weight: 600;
  color: var(--primary);
}

.card-content .list-item a {
  color: var(--primary);
  text-decoration: underline;
  text-decoration-style: dotted;
  text-underline-offset: 2px;
}

.card-content .list-item a:hover {
  text-decoration-style: solid;
  opacity: 0.8;
}

.telos-item {
  display: flex;
  gap: 0.5rem;
  margin: 0.5rem 0;
  font-size: 0.875rem;
}

.telos-id {
  font-family: monospace;
  font-weight: bold;
  color: var(--primary);
  flex-shrink: 0;
}

 
.api-footer {
  display: flex;
  justify-content: center;
  margin-top: 2rem;
}

.api-card {
  background: rgba(0, 0, 0, 0.02);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 0.75rem;
  padding: 2rem;
  text-align: center;
  max-width: 500px;
}

.api-header {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  margin-bottom: 1rem;
  font-family: monospace;
  font-size: 0.875rem;
  font-weight: 600;
  text-transform: uppercase;
}

.api-url {
  display: block;
  font-family: monospace;
  font-size: 1.125rem;
  color: var(--primary);
  margin: 1rem 0;
}

.api-desc {
  opacity: 0.7;
  margin: 1rem 0;
}

.api-docs-btn {
  display: inline-block;
  padding: 0.75rem 1.5rem;
  background: rgba(0, 0, 0, 0.05);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 0.5rem;
  text-decoration: none;
  color: inherit;
  font-family: monospace;
  font-size: 0.875rem;
  transition: all 0.2s;
}

.api-docs-btn:hover {
  background: rgba(0, 0, 0, 0.1);
}

 
.card-content::-webkit-scrollbar {
  width: 6px;
}

.card-content::-webkit-scrollbar-track {
  background: transparent;
}

.card-content::-webkit-scrollbar-thumb {
  background: rgba(0, 0, 0, 0.2);
  border-radius: 3px;
}

 
@media (prefers-color-scheme: dark) {
  .dashboard-card, .api-card, .about-header {
    background: rgba(255, 255, 255, 0.05);
    border-color: rgba(255, 255, 255, 0.1);
  }

  .status-bar {
    background: rgba(255, 255, 255, 0.05);
  }

  .loader {
    border-color: rgba(255, 255, 255, 0.1);
    border-top-color: var(--primary);
  }

  .api-docs-btn {
    background: rgba(255, 255, 255, 0.05);
    border-color: rgba(255, 255, 255, 0.1);
  }

  .api-docs-btn:hover {
    background: rgba(255, 255, 255, 0.1);
  }
}
</style>

<script>

const API_URL = 'https://mcp-daemon.chriswenk.workers.dev';


window.addEventListener('DOMContentLoaded', fetchDaemonData);


setInterval(() => {
  const dateEl = document.getElementById('current-date');
  if (dateEl) {
    dateEl.textContent = new Date().toISOString().slice(0, 10);
  }
}, 1000);

async function fetchDaemonData() {
  try {
    
    document.getElementById('loading-state').style.display = 'flex';
    document.getElementById('error-state').style.display = 'none';
    document.getElementById('dashboard-content').style.display = 'none';

    
    const toolsResponse = await fetch(API_URL, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ jsonrpc: '2.0', method: 'tools/list', id: 1 })
    });

    if (!toolsResponse.ok) throw new Error(`HTTP ${toolsResponse.status}`);

    const toolsData = await toolsResponse.json();
    const toolCount = toolsData.result?.tools?.length || 0;
    const toolCountEl = document.getElementById('tool-count');
    if (toolCountEl) {
      toolCountEl.textContent = `${toolCount} endpoints`;
    }

    
    const dataResponse = await fetch(API_URL, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        jsonrpc: '2.0',
        method: 'tools/call',
        params: { name: 'get_all' },
        id: 2
      })
    });

    if (!dataResponse.ok) throw new Error(`HTTP ${dataResponse.status}`);

    const response = await dataResponse.json();

    
    const daemonData = {};
    if (response.result?.content) {
      response.result.content.forEach(item => {
        if (item.type === 'text' && item.text) {
          const match = item.text.match(/^\[(\w+)\]\n(.+)$/s);
          if (match) {
            const key = match[1].toLowerCase();
            daemonData[key] = match[2].trim();
          }
        }
      });
    }

    
    populateDashboard(daemonData);

    
    document.getElementById('loading-state').style.display = 'none';
    document.getElementById('dashboard-content').style.display = 'block';

    const statusDot = document.getElementById('status-dot');
    const statusText = document.getElementById('status-text');
    if (statusDot) statusDot.style.background = '#10b981';
    if (statusText) statusText.textContent = 'CONNECTED';

  } catch (error) {
    
    document.getElementById('loading-state').style.display = 'none';
    document.getElementById('error-state').style.display = 'flex';

    const errorMsg = document.getElementById('error-message');
    if (errorMsg) {
      errorMsg.textContent = `Connection failed: ${error.message}`;
    }

    
    document.getElementById('dashboard-content').style.display = 'block';

    const statusDot = document.getElementById('status-dot');
    const statusText = document.getElementById('status-text');
    if (statusDot) statusDot.style.background = '#ef4444';
    if (statusText) statusText.textContent = 'OFFLINE';
  }
}

function populateDashboard(data) {
  
  const aboutEl = document.getElementById('about-content');
  if (aboutEl) {
    aboutEl.textContent = data.about || 'Not available';
  }

  
  const narrativeEl = document.getElementById('narrative-content');
  if (narrativeEl) {
    narrativeEl.textContent = data.narrative || 'Not available';
  }

  
  const missionEl = document.getElementById('mission-content');
  if (missionEl) {
    missionEl.textContent = data.mission || 'Not available';
  }

  
  const telosContent = document.getElementById('telos-content');
  if (telosContent) {
    if (data.telos) {
      
      const firstItemMatch = data.telos.match(/-\s*[PMG]\d+:/);
      const introText = firstItemMatch ? data.telos.substring(0, firstItemMatch.index).trim() : '';

      
      
      const itemRegex = /-\s*([PMG]\d+):\s*(.*?)(?=-\s*[PMG]\d+:|$)/gs;
      const telosItems = [];
      let match;

      
      const sectionHeaders = {};

      while ((match = itemRegex.exec(data.telos)) !== null) {
        const id = match[1];
        let text = match[2].trim();

        
        const headerMatch = text.match(/((?:Problems|Missions|Goals|Metrics)\s*\([PMG](?:E)?\)\s*—[^:]*:)/);

        if (headerMatch) {
          
          const sectionLetter = headerMatch[1].match(/\(([PMG](?:E)?)\)/)[1];
          sectionHeaders[sectionLetter] = headerMatch[1];
          
          text = text.replace(headerMatch[0], '').trim();
        }

        if (text) {
          telosItems.push({ id, text });
        }
      }

      let html = '';
      if (introText) {
        
        const headerPlaceholders = [];
        let textWithPlaceholders = introText.replace(/((?:Problems|Missions|Goals|Metrics)\s*\([PMG](?:E)?\)\s*—[^:]*:)/g, (match) => {
          const index = headerPlaceholders.length;
          headerPlaceholders.push(match);
          return `___HEADER_${index}___`;
        });

        
        let formattedIntro = formatText(textWithPlaceholders);

        
        headerPlaceholders.forEach((header, index) => {
          formattedIntro = formattedIntro.replace(`___HEADER_${index}___`, `<br><br><strong>${header}</strong>`);
        });

        html += `<p class="telos-intro" style="margin-bottom: 1.5rem; color: var(--color-neutral-600); line-height: 1.6;">${formattedIntro}</p>`;
      }

      let lastSectionLetter = 'P';
      telosItems.forEach(item => {
        const currentSectionLetter = item.id.charAt(0);

        
        if (currentSectionLetter !== lastSectionLetter && sectionHeaders[currentSectionLetter]) {
          html += `<p class="telos-intro" style="margin-top: 1.5rem; margin-bottom: 1.5rem; color: var(--color-neutral-600); line-height: 1.6; font-weight: 600;">${formatText(sectionHeaders[currentSectionLetter])}</p>`;
          lastSectionLetter = currentSectionLetter;
        }

        html += `<div class="telos-item"><span class="telos-id">${item.id}</span><span>${formatText(item.text)}</span></div>`;
      });

      telosContent.innerHTML = html;
    } else {
      telosContent.innerHTML = '<p class="list-item">Not available</p>';
    }
  }

  
  const locationEl = document.getElementById('location-content');
  if (locationEl) {
    locationEl.textContent = data.current_location || 'Not available';
  }

  
  populateList('books', data.favorite_books);

  
  populateList('movies', data.favorite_movies);

  
  

  
  populateList('predictions', data.predictions);

  
  populateList('preferences', data.preferences);

  
  

  
  const projectsContent = document.getElementById('projects-content');
  if (projectsContent) {
    if (data.projects) {
      
      const projects = data.projects.split('\n').flatMap(line =>
        line.includes('- ') || /\w-\s/.test(line) ? line.split(/\s*-\s+/) : [line]
      ).filter(item => item.trim());

      projectsContent.innerHTML = projects.map(p =>
        `<p class="list-item">${formatText(p)}</p>`
      ).join('');
    } else {
      projectsContent.innerHTML = '<p class="list-item">Not available</p>';
    }
  }

  
  if (data.last_updated) {
    const lastUpdatedEl = document.getElementById('last-updated');
    if (lastUpdatedEl) {
      lastUpdatedEl.textContent = `Updated: ${new Date(data.last_updated).toLocaleDateString()}`;
    }
  }

  
  const currentDateEl = document.getElementById('current-date');
  if (currentDateEl) {
    currentDateEl.textContent = new Date().toISOString().slice(0, 10);
  }
}

function formatText(text) {
  
  text = text.trim().replace(/^[-–—]+|[-–—]+$/g, '');

  
  text = text.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>');

  
  text = text.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank" rel="noopener">$1</a>');

  
  text = text.replace(/(https?:\/\/[^\s<]+)/g, '<a href="$1" target="_blank" rel="noopener">$1</a>');

  
  
  text = text.replace(/^([^":\/\n]+):/g, '<strong>$1:</strong>');

  return text;
}

function populateList(id, data) {
  const content = document.getElementById(`${id}-content`);
  const count = document.getElementById(`${id}-count`);

  if (content) {
    if (data) {
      
      let items = data.split('\n').flatMap(line =>
        line.includes('- ') || /\w-\s/.test(line) ? line.split(/\s*-\s+/) : [line]
      ).filter(item => item.trim());

      content.innerHTML = items.map(item =>
        `<p class="list-item">${formatText(item)}</p>`
      ).join('');
      if (count) count.textContent = items.length;
    } else {
      content.innerHTML = '<p class="list-item">Not available</p>';
      if (count) count.textContent = '0';
    }
  }
}
</script>

]]></content:encoded></item></channel></rss>