# How Skills Are Loaded Lazily in CloddsBot to Prevent Crashes from Missing Native Dependencies

> CloddsBot employs lazy loading for skills, validating gates during discovery and expanding only necessary skills during prompt generation to avoid crashes from missing native dependencies.

- Repository: [AL/CloddsBot](https://github.com/alsk1992/CloddsBot)
- Tags: internals
- Published: 2026-09-14

---

**CloddsBot uses a lazy-loading strategy that validates skill gates during discovery and only expands relevant skills during prompt generation, preventing crashes caused by missing native binaries.**

CloddsBot implements a sophisticated skill management system that avoids startup failures caused by missing native dependencies. Instead of eagerly loading every available skill, the bot employs **lazy loading** combined with proactive gate checking to ensure only viable, relevant skills enter the LLM context. This approach is implemented in the TypeScript source code of the skills loader module.

## The Lazy Loading Architecture

### Initial Skill Discovery and Gate Checking

During initialization, `createSkillManager()` scans multiple directories—including bundled, extra, managed, and workspace paths—to build a map of all skill descriptors. As each `Skill` object is constructed via `loadSkill()`, the system immediately validates the skill's environment requirements.

The `checkGates()` helper function (lines 58–84 in [`src/skills/loader.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/skills/loader.ts)) verifies that required binaries exist on the host system using `hasBin()`, which performs a fast `which` lookup. If a required binary or environment variable is missing, the skill is marked as **disabled** and excluded from subsequent processing, preventing any attempt to invoke non-existent executables.

### Runtime Relevance Evaluation

When the LLM requires skill context for a specific user message, the system invokes `getSkillContextForMessage()`. As noted in the source code comment at line 992 of [`loader.ts`](https://github.com/alsk1992/CloddsBot/blob/main/loader.ts), this function provides "context with lazy skill loading — only expand skills matching the message."

The implementation tokenizes the user message, expands aliases, and calculates relevance scores for each enabled skill based on matches against skill names, descriptions, and sub-command names (lines 1006–1045). Only skills achieving a score ≥ 2 proceed to expansion, ensuring the system ignores irrelevant capabilities regardless of their gate status.

## Dynamic Context Assembly and Token Management

### Intelligent Token Budgeting

To prevent context window overflow, CloddsBot implements dynamic token budgeting (lines 1049–1066 of [`loader.ts`](https://github.com/alsk1992/CloddsBot/blob/main/loader.ts)). The system adjusts the available token budget based on the number of matching skills and query complexity. This ensures that only a carefully selected subset of skills receives full markdown expansion, while remaining skills stay in their compact directory representation.

### Safe Skill Expansion

The final context assembly (lines 1086–1100) expands selected skills into detailed markdown sections. Because skills with missing native dependencies were already disabled during the gate-checking phase, they never reach the relevance-scoring or expansion stages. This architectural guarantee prevents runtime crashes that would otherwise occur when attempting to spawn missing binaries.

## Implementation Example

The following pattern demonstrates how CloddsBot safely handles skills requiring native binaries:

```typescript
// Create the manager (usually done at bot startup)
import { createSkillManager } from './skills/loader';
const skillMgr = createSkillManager('/path/to/workspace', {
  watch: true,
  extraDirs: ['/opt/custom-skills'],
});

// When generating a prompt for the LLM:
const userMessage = "Can you buy POLYM on the Solana DEX?";
const skillContext = skillMgr.getSkillContextForMessage(userMessage);
console.log(skillContext); // Only the Polymarket & Solana-DEX skills are expanded

```

Skills declare their native dependencies in front-matter gates. For example, a Solana DEX skill might specify:

```markdown
---
gates:
  bins: ["solana-cli"]   # requires the native `solana-cli` binary

---

```

If `solana-cli` is not found on the host, `hasBin('solana-cli')` returns `false`, causing `checkGates()` to mark the skill as `enabled = false`. Consequently, `getSkillContextForMessage()` never expands it, avoiding a crash during execution.

## Summary

- **Proactive gate checking** during skill discovery prevents disabled skills from entering the runtime pipeline
- **Lazy context generation** via `getSkillContextForMessage()` only processes skills relevant to the current message
- **Relevance scoring** filters skills by semantic match before expansion, optimizing token usage
- **Dynamic token budgeting** ensures efficient context window utilization while maintaining safety guarantees
- The combination of these mechanisms in [`src/skills/loader.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/skills/loader.ts) ensures CloddsBot remains stable even when native dependencies are missing

## Frequently Asked Questions

### What happens if a native binary is installed after CloddsBot starts?

The skill manager supports file watching via the `watch` option in `createSkillManager()`. When enabled, the system monitors skill directories and can reload skill metadata, re-evaluating gates if the configuration changes or binaries become available during runtime.

### How does CloddsBot determine if a native binary exists?

The `hasBin()` utility function performs a fast `which` lookup on the host system to verify binary availability. This check occurs during the `checkGates()` validation phase in [`src/skills/loader.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/skills/loader.ts) (lines 58–84), ensuring that missing dependencies are detected before any skill code attempts execution.

### Can a skill be partially loaded if some gates pass but others fail?

No. The `checkGates()` function implements an all-or-nothing validation strategy. If any required binary is missing or any required environment variable is unset, the entire skill is marked as disabled. This strict approach prevents partial initialization errors and ensures predictable behavior when native dependencies are unavailable.

### Where does the relevance scoring logic reside?

The relevance calculation occurs in `getSkillContextForMessage()` within [`src/skills/loader.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/skills/loader.ts) (lines 1006–1045). The function tokenizes the user message and compares tokens against skill metadata—including names, descriptions, and sub-commands—to generate a numerical relevance score, filtering for scores ≥ 2.