<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Cradicle Explorer</title>
    <link href="/css/bootstrap/bootstrap.min.css" rel="stylesheet">
    <style>
      .form-control-dark::placeholder {
          color: #aaa;
          opacity: 1;
      }
    </style>
    <link rel="stylesheet" href="/assets/fontawesome/css/all.min.css">
    <link rel="icon" type="image/png" href="/favicon.png">


                <link href="/css/dashboard.css" rel="stylesheet">
                </head>
                <body>
                <header class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
                  <a class="navbar-brand col-md-3 col-lg-2 me-0 px-3 fs-6" href="/">Cradicle Explorer</a>
                  <button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                  </button>
                  <form method="get" action="/cgi-bin/main" style="width:100%;"><input class="form-control form-control-dark w-100 rounded-0 border-0" type="text" name="q" placeholder="Search repos" aria-label="Search"></form>
                  <div class="navbar-nav flex-row">
                    <div class="nav-item text-nowrap">
                      <a class="nav-link px-3 active" href="/cgi-bin/repo?id=z4AFk5tnmJEYfYZQNzWLNtJZGQFpK">ai-ops-automation_ShanClaw</a>
                    </div>
                  </div>
                </header>
                <div class="container-fluid">
                  <div class="row">
                    <nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-dark sidebar collapse">
                      <div class="position-sticky pt-3 sidebar-sticky">
                        <ul class="nav flex-column">
                          <li class="nav-item">
                            <a class="nav-link" href="/cgi-bin/repo?id=z4AFk5tnmJEYfYZQNzWLNtJZGQFpK">
                              <i class="align-text-bottom fa-solid fa-info"></i>
                              Info
                            </a>
                          </li>
                          <li class="nav-item">
                            <a class="nav-link" href="/cgi-bin/repo?id=z4AFk5tnmJEYfYZQNzWLNtJZGQFpK&issue=list">
                              <i class="align-text-bottom fa-solid fa-layer-group"></i>
                              Issues
                            </a>
                          </li>
                          <li class="nav-item">
                            <a class="nav-link" href="/cgi-bin/repo?id=z4AFk5tnmJEYfYZQNzWLNtJZGQFpK&patch=list">
                              <i class="align-text-bottom fa-solid fa-vest-patches"></i>
                              Patches
                            </a>
                          </li>
                          <li class="nav-item">
                            <a class="nav-link" href="/cgi-bin/repo?id=z4AFk5tnmJEYfYZQNzWLNtJZGQFpK&wallet=list">
                              <i class="align-text-bottom fa-solid fa-wallet"></i>
                              Wallets
                            </a>
                          </li>
                          <li class="nav-item">
                            <a class="nav-link active" href="/cgi-bin/repo?id=z4AFk5tnmJEYfYZQNzWLNtJZGQFpK&source=.">
                              <i class="align-text-bottom fa-solid fa-code"></i>
                              Source
                            </a>
                          </li>
                        <h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted text-uppercase">
                          <span></span>
                        </h6>
                        <ul class="nav flex-column mb-2">
                        
    <h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-1 mb-1 text-muted text-uppercase">
      <span>Source</span>
    </h6>
    <li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4AFk5tnmJEYfYZQNzWLNtJZGQFpK&source=.github"><i class="fa-solid fa-folder" style="color:#f0c040;"></i> .github</a></li><li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4AFk5tnmJEYfYZQNzWLNtJZGQFpK&source=cmd"><i class="fa-solid fa-folder" style="color:#f0c040;"></i> cmd</a></li><li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4AFk5tnmJEYfYZQNzWLNtJZGQFpK&source=examples"><i class="fa-solid fa-folder" style="color:#f0c040;"></i> examples</a></li><li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4AFk5tnmJEYfYZQNzWLNtJZGQFpK&source=internal"><i class="fa-solid fa-folder" style="color:#f0c040;"></i> internal</a></li><li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4AFk5tnmJEYfYZQNzWLNtJZGQFpK&source=npm"><i class="fa-solid fa-folder" style="color:#f0c040;"></i> npm</a></li><li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4AFk5tnmJEYfYZQNzWLNtJZGQFpK&source=scripts"><i class="fa-solid fa-folder" style="color:#f0c040;"></i> scripts</a></li><li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4AFk5tnmJEYfYZQNzWLNtJZGQFpK&source=test"><i class="fa-solid fa-folder" style="color:#f0c040;"></i> test</a></li><li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4AFk5tnmJEYfYZQNzWLNtJZGQFpK&file=.gitignore"><i class="fa-solid fa-file" style="color:#888;"></i> .gitignore</a></li><li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4AFk5tnmJEYfYZQNzWLNtJZGQFpK&file=.goreleaser.yaml"><i class="fa-solid fa-file" style="color:#888;"></i> .goreleaser.yaml</a></li><li><a class="nav-link py-0 active" style="padding-left:16px;" href="/cgi-bin/repo?id=z4AFk5tnmJEYfYZQNzWLNtJZGQFpK&file=AGENTS.md"><i class="fa-solid fa-file" style="color:#888;"></i> AGENTS.md</a></li><li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4AFk5tnmJEYfYZQNzWLNtJZGQFpK&file=CHANGELOG.md"><i class="fa-solid fa-file" style="color:#888;"></i> CHANGELOG.md</a></li><li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4AFk5tnmJEYfYZQNzWLNtJZGQFpK&file=CLAUDE.md"><i class="fa-solid fa-file" style="color:#888;"></i> CLAUDE.md</a></li><li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4AFk5tnmJEYfYZQNzWLNtJZGQFpK&file=CONTRIBUTING.md"><i class="fa-solid fa-file" style="color:#888;"></i> CONTRIBUTING.md</a></li><li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4AFk5tnmJEYfYZQNzWLNtJZGQFpK&file=LICENSE"><i class="fa-solid fa-file" style="color:#888;"></i> LICENSE</a></li><li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4AFk5tnmJEYfYZQNzWLNtJZGQFpK&file=README.md"><i class="fa-solid fa-file" style="color:#888;"></i> README.md</a></li><li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4AFk5tnmJEYfYZQNzWLNtJZGQFpK&file=go.mod"><i class="fa-solid fa-file" style="color:#888;"></i> go.mod</a></li><li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4AFk5tnmJEYfYZQNzWLNtJZGQFpK&file=go.sum"><i class="fa-solid fa-file" style="color:#888;"></i> go.sum</a></li><li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4AFk5tnmJEYfYZQNzWLNtJZGQFpK&file=install.sh"><i class="fa-solid fa-file" style="color:#888;"></i> install.sh</a></li><li><a class="nav-link py-0" style="padding-left:16px;" href="/cgi-bin/repo?id=z4AFk5tnmJEYfYZQNzWLNtJZGQFpK&file=main.go"><i class="fa-solid fa-file" style="color:#888;"></i> main.go</a></li>
    
                        </ul>
                      </div>
                    </nav>
                <main class="col-md-9 ms-sm-auto col-lg-10">
                  <div class="container px-1 py-3">
        
<div class="mb-2" style="font-size:1.1rem;"><a href="/cgi-bin/repo?id=z4AFk5tnmJEYfYZQNzWLNtJZGQFpK&source=.">/</a> AGENTS.md</div>
        <div class="list-group">
        <div class="list-group-item">
        <div class="mb-2" style="font-weight:bold;"><i class="fa-solid fa-file"></i> AGENTS.md</div>
        <pre style="margin:0; font-size:0.85rem; overflow-x:auto; color:#fafafa;"><span style="color:#666; user-select:none;">  1</span>  # ShanClaw — Project Guide
<span style="color:#666; user-select:none;">  2</span>  
<span style="color:#666; user-select:none;">  3</span>  ## What This Is
<span style="color:#666; user-select:none;">  4</span>  
<span style="color:#666; user-select:none;">  5</span>  Go CLI tool (`shan`) — the runtime for Shannon AI agents. The primary production stack is **daemon + ShanClaw Desktop + Shannon Cloud**: the daemon connects to Cloud via WebSocket, receives channel messages, runs the agent loop locally with full tool access, and streams results back. ShanClaw also supports interactive TUI, one-shot CLI, MCP server mode, and local scheduled tasks.
<span style="color:#666; user-select:none;">  6</span>  
<span style="color:#666; user-select:none;">  7</span>  ## Tech Stack
<span style="color:#666; user-select:none;">  8</span>  
<span style="color:#666; user-select:none;">  9</span>  - **Go 1.25.7** — `go.mod` is source of truth
<span style="color:#666; user-select:none;"> 10</span>  - **Cobra** — CLI framework
<span style="color:#666; user-select:none;"> 11</span>  - **gorilla/websocket** — daemon WebSocket client (primary production path)
<span style="color:#666; user-select:none;"> 12</span>  - **Bubbletea v1.3.10 + Bubbles v1.0.0** — TUI
<span style="color:#666; user-select:none;"> 13</span>  - **modernc.org/sqlite** — pure-Go SQLite for session FTS5 search index
<span style="color:#666; user-select:none;"> 14</span>  - **adhocore/gronx** — cron expression validation
<span style="color:#666; user-select:none;"> 15</span>  - **chromedp** — browser automation (isolated Chrome profile)
<span style="color:#666; user-select:none;"> 16</span>  - **mcp-go** — MCP client/server
<span style="color:#666; user-select:none;"> 17</span>  - **adrg/frontmatter** — YAML frontmatter parsing for SKILL.md files
<span style="color:#666; user-select:none;"> 18</span>  
<span style="color:#666; user-select:none;"> 19</span>  ## Project Structure
<span style="color:#666; user-select:none;"> 20</span>  
<span style="color:#666; user-select:none;"> 21</span>  ```
<span style="color:#666; user-select:none;"> 22</span>  cmd/
<span style="color:#666; user-select:none;"> 23</span>    root.go              # entry, one-shot mode, MCP serve
<span style="color:#666; user-select:none;"> 24</span>    daemon.go            # shan daemon start/stop/status
<span style="color:#666; user-select:none;"> 25</span>    schedule.go          # scheduled task management
<span style="color:#666; user-select:none;"> 26</span>    update.go            # self-update command
<span style="color:#666; user-select:none;"> 27</span>  
<span style="color:#666; user-select:none;"> 28</span>  internal/
<span style="color:#666; user-select:none;"> 29</span>    daemon/              # PRIMARY PRODUCTION PATH
<span style="color:#666; user-select:none;"> 30</span>      server.go          # HTTP API server
<span style="color:#666; user-select:none;"> 31</span>      runner.go          # agent run orchestration, session routing, output format profiles
<span style="color:#666; user-select:none;"> 32</span>      client.go          # WebSocket client with reconnect, bounded concurrency
<span style="color:#666; user-select:none;"> 33</span>      router.go          # SessionCache, route locking
<span style="color:#666; user-select:none;"> 34</span>      approval.go        # interactive tool approval over WS
<span style="color:#666; user-select:none;"> 35</span>      types.go           # daemon request/response types, disconnect, approval messages
<span style="color:#666; user-select:none;"> 36</span>      events.go          # EventBus ring buffer for daemon/SSE subscribers
<span style="color:#666; user-select:none;"> 37</span>      session_cwd.go     # cloud-source scratch CWD allocator (ephemeral per-session tmp dir)
<span style="color:#666; user-select:none;"> 38</span>    agent/
<span style="color:#666; user-select:none;"> 39</span>      loop.go            # AgentLoop.Run() — core agentic loop
<span style="color:#666; user-select:none;"> 40</span>      tools.go           # Tool interface, ToolRegistry, filtering, schemas
<span style="color:#666; user-select:none;"> 41</span>      partition.go       # read-only batching, executeBatches
<span style="color:#666; user-select:none;"> 42</span>      spill.go           # large tool result spill-to-disk
<span style="color:#666; user-select:none;"> 43</span>      deferred.go        # deferred tool loading (tool_search)
<span style="color:#666; user-select:none;"> 44</span>      statecache.go      # state-aware tool result cache keyed by read/write state
<span style="color:#666; user-select:none;"> 45</span>      resultshape.go     # tree result shaping and stable change summaries
<span style="color:#666; user-select:none;"> 46</span>      microcompact.go    # Tier 2 semantic compaction for large native tool results
<span style="color:#666; user-select:none;"> 47</span>      delta.go           # DeltaProvider interface, TemporalDelta (date rollover)
<span style="color:#666; user-select:none;"> 48</span>      loopdetect.go      # stuck-loop detectors
<span style="color:#666; user-select:none;"> 49</span>      readtracker.go     # read-before-edit enforcement
<span style="color:#666; user-select:none;"> 50</span>      approval_cache.go  # per-turn approval caching
<span style="color:#666; user-select:none;"> 51</span>      normalize.go       # response normalization
<span style="color:#666; user-select:none;"> 52</span>      skill_discovery.go # Per-turn small-model skill matching (discoverRelevantSkills)
<span style="color:#666; user-select:none;"> 53</span>    agents/
<span style="color:#666; user-select:none;"> 54</span>      loader.go          # LoadAgent, ListAgents, ParseAgentMention
<span style="color:#666; user-select:none;"> 55</span>      api.go             # daemon-side agent CRUD
<span style="color:#666; user-select:none;"> 56</span>      validate.go        # agent validation and builtin commands
<span style="color:#666; user-select:none;"> 57</span>      embed.go           # EnsureBuiltins, MaterializeBuiltin, bundled agents
<span style="color:#666; user-select:none;"> 58</span>      builtin/           # Bundled agent definitions (explorer, reviewer)
<span style="color:#666; user-select:none;"> 59</span>    client/
<span style="color:#666; user-select:none;"> 60</span>      gateway.go         # GatewayClient: Complete, CompleteStream, ListTools
<span style="color:#666; user-select:none;"> 61</span>      sse.go             # SSE event parsing
<span style="color:#666; user-select:none;"> 62</span>      ollama.go          # Ollama provider via OpenAI-compatible chat/tool APIs
<span style="color:#666; user-select:none;"> 63</span>    config/
<span style="color:#666; user-select:none;"> 64</span>      config.go          # multi-level config loading and merge
<span style="color:#666; user-select:none;"> 65</span>      settings.go        # UI settings
<span style="color:#666; user-select:none;"> 66</span>      setup.go           # setup wizard
<span style="color:#666; user-select:none;"> 67</span>    cwdctx/
<span style="color:#666; user-select:none;"> 68</span>      cwdctx.go          # session-scoped CWD: context propagation, path resolution
<span style="color:#666; user-select:none;"> 69</span>    context/
<span style="color:#666; user-select:none;"> 70</span>      window.go          # token estimation, compaction shaping
<span style="color:#666; user-select:none;"> 71</span>      summarize.go       # two-phase conversation summary generation
<span style="color:#666; user-select:none;"> 72</span>      persist.go         # write-before-compact memory extraction
<span style="color:#666; user-select:none;"> 73</span>    session/
<span style="color:#666; user-select:none;"> 74</span>      store.go           # session JSON persistence
<span style="color:#666; user-select:none;"> 75</span>      manager.go         # session lifecycle, search, OnClose callbacks
<span style="color:#666; user-select:none;"> 76</span>      index.go           # SQLite FTS5 search index
<span style="color:#666; user-select:none;"> 77</span>      title.go           # session title generation
<span style="color:#666; user-select:none;"> 78</span>    prompt/
<span style="color:#666; user-select:none;"> 79</span>      builder.go         # static/stable/volatile prompt assembly, output profiles
<span style="color:#666; user-select:none;"> 80</span>    instructions/
<span style="color:#666; user-select:none;"> 81</span>      loader.go          # instructions, memory, custom commands
<span style="color:#666; user-select:none;"> 82</span>    tools/
<span style="color:#666; user-select:none;"> 83</span>      register.go        # local + MCP + gateway tool registration
<span style="color:#666; user-select:none;"> 84</span>      schedule.go        # schedule_create/list/update/remove tools
<span style="color:#666; user-select:none;"> 85</span>      session_search.go  # session_search tool
<span style="color:#666; user-select:none;"> 86</span>      mcp_tool.go        # MCPTool adapter
<span style="color:#666; user-select:none;"> 87</span>      server.go          # ServerTool adapter (gateway tools)
<span style="color:#666; user-select:none;"> 88</span>    skills/
<span style="color:#666; user-select:none;"> 89</span>      registry.go        # skill metadata
<span style="color:#666; user-select:none;"> 90</span>      loader.go          # skill loading
<span style="color:#666; user-select:none;"> 91</span>      validate.go        # skill name validation
<span style="color:#666; user-select:none;"> 92</span>    memory/
<span style="color:#666; user-select:none;"> 93</span>      types.go             # Wire schemas mirroring the Kocoro Cloud memory sidecar HTTP contract
<span style="color:#666; user-select:none;"> 94</span>      errclass.go          # ErrorClass enum + ClassifyHTTP (sub_code → class)
<span style="color:#666; user-select:none;"> 95</span>      config.go            # LoadConfig, ResolveAPIKey, ResolveEndpoint
<span style="color:#666; user-select:none;"> 96</span>      tenant.go            # sha256 fingerprint + tenant-switch detection
<span style="color:#666; user-select:none;"> 97</span>      audit.go             # AuditLogger interface (boolean-only key/endpoint state)
<span style="color:#666; user-select:none;"> 98</span>      client.go            # UDS HTTP client (Query/Reload/Health, X-Request-ID, ctx-cancel dial)
<span style="color:#666; user-select:none;"> 99</span>      sidecar.go           # Spawn/WaitReady/Shutdown + AttachPolicy + Supervisor
<span style="color:#666; user-select:none;">100</span>      bundle.go            # Puller: manifest fetch, tenant check, sandboxed stage, atomic install, retention
<span style="color:#666; user-select:none;">101</span>      service.go           # Orchestrator: status FSM, supervisor + puller goroutines, NewServiceAttached
<span style="color:#666; user-select:none;">102</span>    mcp/
<span style="color:#666; user-select:none;">103</span>      client.go          # MCP client manager
<span style="color:#666; user-select:none;">104</span>      server.go          # MCP server
<span style="color:#666; user-select:none;">105</span>      chrome.go          # Playwright Chrome profile/CDP lifecycle management
<span style="color:#666; user-select:none;">106</span>    runstatus/
<span style="color:#666; user-select:none;">107</span>      runstatus.go       # user-facing run state/error classification
<span style="color:#666; user-select:none;">108</span>    schedule/
<span style="color:#666; user-select:none;">109</span>      schedule.go        # schedule CRUD, atomic writes, validation
<span style="color:#666; user-select:none;">110</span>      launchd_darwin.go  # plist generation, launchctl
<span style="color:#666; user-select:none;">111</span>      launchd_stub.go    # non-darwin stub
<span style="color:#666; user-select:none;">112</span>    permissions/
<span style="color:#666; user-select:none;">113</span>      permissions.go     # hard-block &gt; denied &gt; split compounds &gt; allowed &gt; default safe &gt; ask
<span style="color:#666; user-select:none;">114</span>    audit/
<span style="color:#666; user-select:none;">115</span>      audit.go           # JSON-lines logger, redaction
<span style="color:#666; user-select:none;">116</span>    hooks/
<span style="color:#666; user-select:none;">117</span>      hooks.go           # PreToolUse/PostToolUse/SessionStart/Stop
<span style="color:#666; user-select:none;">118</span>    tui/
<span style="color:#666; user-select:none;">119</span>      app.go             # Bubbletea app
<span style="color:#666; user-select:none;">120</span>      doctor.go          # TUI diagnostic checks
<span style="color:#666; user-select:none;">121</span>      compact.go         # TUI /compact command
<span style="color:#666; user-select:none;">122</span>    update/
<span style="color:#666; user-select:none;">123</span>      selfupdate.go      # GitHub release auto-update
<span style="color:#666; user-select:none;">124</span>    sync/
<span style="color:#666; user-select:none;">125</span>      sync.go            # Run(ctx, deps) — flock, marker read, scan, batch, upload, write, audit
<span style="color:#666; user-select:none;">126</span>      marker.go          # Marker + FailedEntry; atomic read/write; sidecar on unknown version
<span style="color:#666; user-select:none;">127</span>      config.go          # Typed view of sync.* config keys
<span style="color:#666; user-select:none;">128</span>      scanner.go         # Multi-dir candidate discovery; failed-retry union; exclusions
<span style="color:#666; user-select:none;">129</span>      batcher.go         # Marshal-once; dual-cap (sessions+bytes) packing; oversized + load-error rejection
<span style="color:#666; user-select:none;">130</span>      uploader.go        # Uploader interface; CloudUploader + DryRunUploader; response anomaly normalization
<span style="color:#666; user-select:none;">131</span>      backoff.go         # Reason classification + transient backoff math
<span style="color:#666; user-select:none;">132</span>  ```
<span style="color:#666; user-select:none;">133</span>  
<span style="color:#666; user-select:none;">134</span>  ## Key Conventions
<span style="color:#666; user-select:none;">135</span>  
<span style="color:#666; user-select:none;">136</span>  ### Kocoro Skill Co-Maintenance
<span style="color:#666; user-select:none;">137</span>  The `kocoro` bundled skill (`internal/skills/bundled/skills/kocoro/`) is a platform configuration assistant. Its SKILL.md and reference files (`references/*.md`) describe daemon API endpoints, config fields, and workflows. Kocoro is the AI&#x27;s only source of truth for ShanClaw&#x27;s HTTP surface — missing docs cause it to hallucinate workarounds. **Adding a new endpoint or feature counts as a trigger, not only modifying existing ones**; any `mux.HandleFunc(...)` in `internal/daemon/server.go` must have a matching reference entry. See CLAUDE.md for the full mapping.
<span style="color:#666; user-select:none;">138</span>  
<span style="color:#666; user-select:none;">139</span>  ### Agent Names
<span style="color:#666; user-select:none;">140</span>  
<span style="color:#666; user-select:none;">141</span>  Must match `^[a-z0-9][a-z0-9_-]{0,63}$`. Validate before any path concatenation to prevent traversal.
<span style="color:#666; user-select:none;">142</span>  
<span style="color:#666; user-select:none;">143</span>  ### Tool Priority
<span style="color:#666; user-select:none;">144</span>  
<span style="color:#666; user-select:none;">145</span>  Local tools &gt; MCP tools &gt; Gateway tools. Deduplicate by name in the registry.
<span style="color:#666; user-select:none;">146</span>  
<span style="color:#666; user-select:none;">147</span>  ### Skill Discovery
<span style="color:#666; user-select:none;">148</span>  
<span style="color:#666; user-select:none;">149</span>  Three-layer system for triggering `use_skill`:
<span style="color:#666; user-select:none;">150</span>  1. **Skill listing** — full descriptions embedded in the scaffolded user message on first turn.
<span style="color:#666; user-select:none;">151</span>  2. **Semantic discovery** — blocking `model_tier: &quot;small&quot;` call on iteration 0 (5s timeout). Gated by `agent.skill_discovery` config (default `true`).
<span style="color:#666; user-select:none;">152</span>  3. **Fallback catalog** — `use_skill` tool description includes all loaded skill names.
<span style="color:#666; user-select:none;">153</span>  
<span style="color:#666; user-select:none;">154</span>  **Skill allowed-tools** uses execution-time denial, not schema filtering, to keep the tools array byte-stable for prompt cache.
<span style="color:#666; user-select:none;">155</span>  
<span style="color:#666; user-select:none;">156</span>  ### Permission Model
<span style="color:#666; user-select:none;">157</span>  
<span style="color:#666; user-select:none;">158</span>  ```
<span style="color:#666; user-select:none;">159</span>  hard-block constants → denied_commands → compound-command splitting → allowed_commands → default safe → RequiresApproval + SafeChecker
<span style="color:#666; user-select:none;">160</span>  ```
<span style="color:#666; user-select:none;">161</span>  
<span style="color:#666; user-select:none;">162</span>  Unknown tools are denied by default.
<span style="color:#666; user-select:none;">163</span>  
<span style="color:#666; user-select:none;">164</span>  ### Daemon Architecture
<span style="color:#666; user-select:none;">165</span>  
<span style="color:#666; user-select:none;">166</span>  - Daemon connects to Shannon Cloud via WebSocket, receives channel messages, and runs the agent loop locally.
<span style="color:#666; user-select:none;">167</span>  - Route keys are computed as:
<span style="color:#666; user-select:none;">168</span>    - `agent:&lt;name&gt;` for agent-scoped sessions
<span style="color:#666; user-select:none;">169</span>    - `session:&lt;id&gt;` for explicit session resume
<span style="color:#666; user-select:none;">170</span>    - `default:&lt;source&gt;:&lt;channel&gt;` for routed channel sessions
<span style="color:#666; user-select:none;">171</span>  - Routed managers are long-lived. Ephemeral runs (for example bypass/heartbeat paths) use short-lived managers.
<span style="color:#666; user-select:none;">172</span>  - Output formatting uses profiles, not per-channel syntax:
<span style="color:#666; user-select:none;">173</span>    - `markdown` is the default
<span style="color:#666; user-select:none;">174</span>    - `plain` is used for cloud-distributed channels where Shannon Cloud owns final rendering
<span style="color:#666; user-select:none;">175</span>  - Tool status `running` is emitted at actual execution start, not during approval/permission checks.
<span style="color:#666; user-select:none;">176</span>  - Large tool results spill to `~/.shannon/tmp/` and are cleaned up:
<span style="color:#666; user-select:none;">177</span>    - per-run in daemon and TUI
<span style="color:#666; user-select:none;">178</span>    - on manager close in one-shot mode
<span style="color:#666; user-select:none;">179</span>  - **Session sync** (`internal/sync/`): uploads local session JSON to Shannon Cloud once per day (opt-in via `sync.enabled`). Single entry point `sync.Run`; called from the daemon ticker and the `shan sessions sync` CLI; flock + atomic marker write serialize concurrent callers. Per-session ACK with persistent `marker.failed` bookkeeping; permanent reasons (`size_limit_exceeded`, `load_error`) stay forever and self-heal on session edit.
<span style="color:#666; user-select:none;">180</span>  - **Memory client** (`internal/memory/`, Phase 2.3): daemon owns sidecar lifecycle (spawn / health / restart / shutdown) and the 24h bundle pull loop. Tool `memory_recall` (`internal/tools/memory.go`) delegates to `memory.Service.Query` via UDS; falls back to `session_search` + MEMORY.md whenever `Service.Status() != Ready`. CLI/TUI use `memory.AttachPolicy` (probe-only, never spawn) and connect via `memory.NewServiceAttached`. Privacy invariant: the resolved API key bytes never reach disk or audit logs (only `sha256[:16]` fingerprint in `&lt;bundle_root&gt;/.tenant_fingerprint`).
<span style="color:#666; user-select:none;">181</span>  
<span style="color:#666; user-select:none;">182</span>  ### Turn Lifecycle
<span style="color:#666; user-select:none;">183</span>  
<span style="color:#666; user-select:none;">184</span>  The agent loop declares an explicit phase state machine (`internal/agent/phase.go`) that external observers can reason about:
<span style="color:#666; user-select:none;">185</span>  
<span style="color:#666; user-select:none;">186</span>  - **Phases**: `PhaseAwaitingLLM`, `PhaseExecutingTools`, `PhaseCompacting`, `PhaseAwaitingApproval`, `PhaseRetryingLLM`, `PhaseForceStop`, `PhaseInjectingMessage`, etc. Only `PhaseAwaitingLLM` and `PhaseForceStop` count as idle for the watchdog.
<span style="color:#666; user-select:none;">187</span>  - **Idle watchdog**: with `agent.idle_soft_timeout_secs` &gt; 0 the daemon fires an `EventRunStatus` event (code `idle_soft`) after that long in an idle-counted phase. With `agent.idle_hard_timeout_secs` &gt; 0 the run is cancelled with `ErrHardIdleTimeout` — the partial transcript is still persisted (soft error). Defaults: soft=90, hard=0 (visibility-only).
<span style="color:#666; user-select:none;">188</span>  - **Mid-turn checkpoint**: after each tool batch, after successful reactive compaction, and before a force-stop, the daemon rebuilds the on-disk session from a baseline + current loop snapshot. The same rebuild runs at final save so a turn is never persisted twice. `session.Session.InProgress=true` on reload indicates a crash-recovered session with a partial transcript.
<span style="color:#666; user-select:none;">189</span>  - **Event types**: `EventRunStatus` (watchdog soft/hard, LLM retries) joins the existing `EventAgentReply`, `EventToolStatus`, `EventApprovalRequest` stream.
<span style="color:#666; user-select:none;">190</span>  
<span style="color:#666; user-select:none;">191</span>  ### Browser Preview Bridge
<span style="color:#666; user-select:none;">192</span>  
<span style="color:#666; user-select:none;">193</span>  For daemon runs with Playwright, `browser_navigate(file://…)` is transparently rewritten to a short-lived `http://127.0.0.1/&lt;token&gt;/&lt;name&gt;` URL served by a loopback HTTP server bound per-session:
<span style="color:#666; user-select:none;">194</span>  - Fail-closed allowlist populated from the effective session CWD + user-attached paths. Browser reach never exceeds `permissions.CheckFilePath`.
<span style="color:#666; user-select:none;">195</span>  - Symlinks resolved on both sides of the allowlist check; escapes rejected.
<span style="color:#666; user-select:none;">196</span>  - Random 16-byte hex token per file; no directory listing; teardown on session close.
<span style="color:#666; user-select:none;">197</span>  
<span style="color:#666; user-select:none;">198</span>  ### Config Merge Order
<span style="color:#666; user-select:none;">199</span>  
<span style="color:#666; user-select:none;">200</span>  1. `~/.shannon/config.yaml` (global)
<span style="color:#666; user-select:none;">201</span>  2. `.shannon/config.yaml` (project)
<span style="color:#666; user-select:none;">202</span>  3. `.shannon/config.local.yaml` (local, gitignored)
<span style="color:#666; user-select:none;">203</span>  
<span style="color:#666; user-select:none;">204</span>  Scalars override, lists merge+dedup, structs merge field-by-field. MCP server env var casing is preserved via direct YAML re-read.
<span style="color:#666; user-select:none;">205</span>  
<span style="color:#666; user-select:none;">206</span>  ### File Paths
<span style="color:#666; user-select:none;">207</span>  
<span style="color:#666; user-select:none;">208</span>  - Agent definitions: `~/.shannon/agents/&lt;name&gt;/AGENT.md`, `MEMORY.md`, `config.yaml`, `commands/*.md`, `_attached.yaml`
<span style="color:#666; user-select:none;">209</span>  - Global skills: `~/.shannon/skills/&lt;skill-name&gt;/SKILL.md`
<span style="color:#666; user-select:none;">210</span>  - Sessions: `~/.shannon/sessions/` or `~/.shannon/agents/&lt;name&gt;/sessions/`
<span style="color:#666; user-select:none;">211</span>  - Session index: `&lt;sessions-dir&gt;/sessions.db`
<span style="color:#666; user-select:none;">212</span>  - Spill files: `~/.shannon/tmp/tool_result_&lt;session&gt;_&lt;call_id&gt;.txt`
<span style="color:#666; user-select:none;">213</span>  - Schedule index: `~/.shannon/schedules.json`
<span style="color:#666; user-select:none;">214</span>  - Schedule plists: `~/Library/LaunchAgents/com.shannon.schedule.&lt;id&gt;.plist`
<span style="color:#666; user-select:none;">215</span>  - Sync marker: `~/.shannon/sync_marker.json`
<span style="color:#666; user-select:none;">216</span>  - Sync lock (flock): `~/.shannon/sync.lock` (never delete)
<span style="color:#666; user-select:none;">217</span>  - Sync dry-run outbox: `~/.shannon/sync_outbox/` (only when `sync.dry_run=true`)
<span style="color:#666; user-select:none;">218</span>  - Audit log: `~/.shannon/logs/audit.log`
<span style="color:#666; user-select:none;">219</span>  - Schedule logs: `~/.shannon/logs/schedule-&lt;id&gt;.log`
<span style="color:#666; user-select:none;">220</span>  - Memory sidecar socket: `~/.shannon/memory.sock`
<span style="color:#666; user-select:none;">221</span>  - Memory bundle root: `~/.shannon/memory/` (with `bundles/&lt;ts&gt;/`, `current` symlink, `.tenant_fingerprint`, `bundle.lock`)
<span style="color:#666; user-select:none;">222</span>  
<span style="color:#666; user-select:none;">223</span>  ### Prompt Cache
<span style="color:#666; user-select:none;">224</span>  
<span style="color:#666; user-select:none;">225</span>  Source-routed TTL: channels/TUI get 1h, one-shot/subagent paths get 5m (fail-cheap default). `cache_source` tags every LLM call and propagates on the wire. `normalizeToolInput` canonicalizes nested JSON for byte stability. See `docs/cache-strategy.md` for breakpoint layout, source table, env-var overrides, and maintenance playbook.
<span style="color:#666; user-select:none;">226</span>  
<span style="color:#666; user-select:none;">227</span>  ### Context Management
<span style="color:#666; user-select:none;">228</span>  
<span style="color:#666; user-select:none;">229</span>  - **Proactive compaction**: persist learnings, then generate a two-phase summary, then shape history when nearing the context window.
<span style="color:#666; user-select:none;">230</span>  - **Reactive compaction**: on context-length error, emergency compact once and retry once. `reactiveCompacted` prevents loops.
<span style="color:#666; user-select:none;">231</span>  - **Tiered result compression**:
<span style="color:#666; user-select:none;">232</span>    - Tier 1: old results collapse to metadata only
<span style="color:#666; user-select:none;">233</span>    - Tier 2: mid-age results use head+tail truncation, with micro-compact for large native tool results when a small-model completer is available
<span style="color:#666; user-select:none;">234</span>    - Tier 3: recent results stay full
<span style="color:#666; user-select:none;">235</span>  - **Deferred tool loading**: when the toolset is large and includes deferred sources, MCP/gateway tools are exposed as summaries until the model loads schemas through `tool_search`.
<span style="color:#666; user-select:none;">236</span>  - **Memory staleness**: dated memory headings get freshness annotations like `[today]` and `[N days ago]`.
<span style="color:#666; user-select:none;">237</span>  - **System reminders**: short reminder blocks are appended to high-signal tool results (`file_read`, `file_write`, `file_edit`, `bash`) to reinforce key instructions in long sessions.
<span style="color:#666; user-select:none;">238</span>  - **Disk spill**: very large tool outputs are written to disk and replaced in context with a short preview plus a readable path.
<span style="color:#666; user-select:none;">239</span>  
<span style="color:#666; user-select:none;">240</span>  ### Anti-Hallucination
<span style="color:#666; user-select:none;">241</span>  
<span style="color:#666; user-select:none;">242</span>  - XML `&lt;tool_exec&gt;` delimiters use random hex call IDs.
<span style="color:#666; user-select:none;">243</span>  - Preamble text is suppressed when the response contains tool calls.
<span style="color:#666; user-select:none;">244</span>  - Fabricated tool calls are detected and stripped.
<span style="color:#666; user-select:none;">245</span>  
<span style="color:#666; user-select:none;">246</span>  ## Testing
<span style="color:#666; user-select:none;">247</span>  
<span style="color:#666; user-select:none;">248</span>  ```bash
<span style="color:#666; user-select:none;">249</span>  go test ./...                    # all tests
<span style="color:#666; user-select:none;">250</span>  go test ./internal/agent/ -v     # agent loop, batching, compaction, spill, deferred
<span style="color:#666; user-select:none;">251</span>  go test ./internal/daemon/ -v    # daemon WS client, router, runner
<span style="color:#666; user-select:none;">252</span>  go test ./internal/agents/ -v    # agent loader
<span style="color:#666; user-select:none;">253</span>  go test ./internal/schedule/ -v  # schedule CRUD + plist tests
<span style="color:#666; user-select:none;">254</span>  go test ./test/ -v               # E2E coverage
<span style="color:#666; user-select:none;">255</span>  go test ./test/e2e/ -v           # E2E offline: agents, schedule, session, MCP, cache
<span style="color:#666; user-select:none;">256</span>  SHANNON_E2E_LIVE=1 go test ./test/e2e/ -v  # E2E live: one-shot, bundled agents (daemon skipped until isolated)
<span style="color:#666; user-select:none;">257</span>  go build ./...                   # build check
<span style="color:#666; user-select:none;">258</span>  ```
<span style="color:#666; user-select:none;">259</span>  
<span style="color:#666; user-select:none;">260</span>  Schedule tests use temp directories and never write to the real LaunchAgents directory.
<span style="color:#666; user-select:none;">261</span>  
<span style="color:#666; user-select:none;">262</span>  E2E tests in `test/e2e/` split into offline (no API) and live (`SHANNON_E2E_LIVE=1`). Run live tests before releases.
<span style="color:#666; user-select:none;">263</span>  
<span style="color:#666; user-select:none;">264</span>  ## Building &amp; Releasing
<span style="color:#666; user-select:none;">265</span>  
<span style="color:#666; user-select:none;">266</span>  - GoReleaser: `.goreleaser.yaml`
<span style="color:#666; user-select:none;">267</span>  - npm package: `@kocoro/shanclaw`
<span style="color:#666; user-select:none;">268</span>  - Versioning is PATCH-only (`0.0.x`) unless explicitly directed otherwise
<span style="color:#666; user-select:none;">269</span>  - Release flow: tag → push tag → CI builds and publishes
<span style="color:#666; user-select:none;">270</span>  - `docs/` is gitignored — documentation lives locally only
<span style="color:#666; user-select:none;">271</span>  
<span style="color:#666; user-select:none;">272</span>  ## Tool Inventory
<span style="color:#666; user-select:none;">273</span>  
<span style="color:#666; user-select:none;">274</span>  ### Core Local Tools
<span style="color:#666; user-select:none;">275</span>  
<span style="color:#666; user-select:none;">276</span>  - File ops: `file_read`, `file_write`, `file_edit`, `glob`, `grep`, `directory_list`
<span style="color:#666; user-select:none;">277</span>  - Shell/system: `bash`, `system_info`, `process`, `http`, `think`
<span style="color:#666; user-select:none;">278</span>  - macOS GUI: `accessibility`, `applescript`, `screenshot`, `computer`, `clipboard`, `notify`, `browser`, `wait_for`, `ghostty`
<span style="color:#666; user-select:none;">279</span>  - Schedule: `schedule_create`, `schedule_list`, `schedule_update`, `schedule_remove`
<span style="color:#666; user-select:none;">280</span>  - Memory: `memory_append`
<span style="color:#666; user-select:none;">281</span>  - Skills: `use_skill`
<span style="color:#666; user-select:none;">282</span>  
<span style="color:#666; user-select:none;">283</span>  ### Runtime-Conditional Tools
<span style="color:#666; user-select:none;">284</span>  
<span style="color:#666; user-select:none;">285</span>  - Session: `session_search` when a session manager is present
<span style="color:#666; user-select:none;">286</span>  - Cloud: `cloud_delegate` when gateway/cloud access is enabled
<span style="color:#666; user-select:none;">287</span>  - Meta: `tool_search` in deferred mode only
</pre>
        </div>
        </div>

</div>
</main>
</div>
</div>


</body>
</html>

