Claude
Skills
Sign in
Back

cabinet-ai-knowledge-base

Included with Lifetime
$97 forever

AI-first knowledge base and startup OS with file-based storage, AI agents, scheduled jobs, and embedded apps

General

What this skill does


# Cabinet AI Knowledge Base

> Skill by [ara.so](https://ara.so) — Daily 2026 Skills collection.

Cabinet is an AI-first startup OS and knowledge base where everything lives as markdown files on disk. No database, no vendor lock-in — self-hosted with AI agents that have memory, scheduled jobs, embedded HTML apps, git-backed history, and a full web terminal.

---

## Installation

### Quick Start (recommended)

```bash
npx create-cabinet@latest
cd cabinet
npm run dev:all
```

Open [http://localhost:3000](http://localhost:3000) — the onboarding wizard builds your AI team in 5 questions.

### Manual Clone

```bash
git clone https://github.com/hilash/cabinet.git
cd cabinet
npm install
cp .env.example .env.local
npm run dev:all
```

### Prerequisites

- Node.js 20+
- Claude Code CLI: `npm install -g @anthropic-ai/claude-code`
- macOS or Linux (Windows via WSL)

---

## Environment Configuration

```bash
# .env.local
KB_PASSWORD=your_optional_password   # Leave empty for no auth
DOMAIN=localhost                     # Or your custom domain
```

---

## Key Commands

```bash
npm run dev          # Next.js dev server on port 3000
npm run dev:daemon   # WebSocket + job scheduler on port 3001
npm run dev:all      # Both servers together (use this for development)
npm run build        # Production build
npm run start        # Production mode (both servers)
```

---

## Architecture

```
cabinet/
  src/
    app/api/         → Next.js API routes
    components/      → React components (sidebar, editor, agents, jobs, terminal)
    stores/          → Zustand state management
    lib/             → Storage, markdown, git, agents, jobs
  server/
    cabinet-daemon.ts → WebSocket + job scheduler + agent executor
  data/
    .agents/.library/ → 20 pre-built agent templates
    getting-started/  → Default KB pages
```

**Tech stack:** Next.js 16, TypeScript, Tailwind CSS, shadcn/ui, Tiptap, Zustand, xterm.js, node-cron

---

## Project Structure (data directory)

Cabinet stores everything as markdown files under `data/`:

```
data/
  getting-started/
    index.md
  my-project/
    index.md
    research.md
    index.html        ← Embedded HTML app (auto-rendered as iframe)
  .agents/
    .library/
      ceo.md
      product-manager.md
      researcher.md
    active/
      my-ceo/
        index.md      ← Agent definition
        memory.md     ← Agent memory (auto-updated)
```

---

## Agent Definition Format

Agents are defined as markdown files with YAML frontmatter:

```markdown
---
name: Research Scout
role: researcher
schedule: "0 */6 * * *"   # Cron: every 6 hours
skills:
  - web-search
  - summarization
  - reddit-scout
goals:
  - Monitor competitor activity
  - Surface trending topics in AI tooling
  - File weekly summary reports
---

# Research Scout

You are a research agent for [Company Name]. Your job is to...

## Memory

<!-- Agent memory is auto-appended here by the daemon -->
```

---

## Creating a Custom Agent

### Via the UI

1. Navigate to the Agents panel in the sidebar
2. Click "New Agent" and select a template or start blank
3. Fill in role, goals, and schedule
4. Cabinet creates `data/.agents/active/<agent-name>/index.md`

### Programmatically

```typescript
// src/lib/agents.ts pattern — create an agent file directly
import fs from 'fs/promises'
import path from 'path'

const agentDir = path.join(process.cwd(), 'data', '.agents', 'active', 'my-agent')

await fs.mkdir(agentDir, { recursive: true })

await fs.writeFile(
  path.join(agentDir, 'index.md'),
  `---
name: My Custom Agent
role: analyst
schedule: "0 9 * * 1"
goals:
  - Analyze weekly metrics
  - Post summary to #reports channel
---

# My Custom Agent

You are a data analyst agent. Every Monday at 9am you will...
`
)
```

---

## Scheduled Jobs (Cron)

Agents use standard cron syntax in their frontmatter `schedule` field:

```yaml
# Common schedule patterns
schedule: "0 */6 * * *"    # Every 6 hours
schedule: "0 9 * * 1"      # Every Monday at 9am
schedule: "0 8 * * *"      # Every day at 8am
schedule: "*/30 * * * *"   # Every 30 minutes
schedule: "0 0 * * 0"      # Weekly on Sunday midnight
```

The Cabinet daemon (`server/cabinet-daemon.ts`) reads agent files and registers jobs via `node-cron`. Jobs run agent prompts through Claude Code and write results back to the agent's memory file.

---

## Embedded HTML Apps

Drop an `index.html` in any folder under `data/` — Cabinet automatically renders it as an embedded iframe with a full-screen toggle:

```
data/
  my-dashboard/
    index.html    ← Cabinet renders this as an embedded app
    data.json
    style.css
```

Example `data/my-dashboard/index.html`:

```html
<!DOCTYPE html>
<html>
<head>
  <title>Metrics Dashboard</title>
  <style>
    body { font-family: sans-serif; padding: 20px; background: #1a1a1a; color: #eee; }
    .metric { font-size: 2rem; font-weight: bold; color: #55c938; }
  </style>
</head>
<body>
  <h1>Weekly Metrics</h1>
  <div class="metric" id="count">Loading...</div>
  <script>
    fetch('./data.json')
      .then(r => r.json())
      .then(d => document.getElementById('count').textContent = d.value)
  </script>
</body>
</html>
```

No build step required. Version controlled via git automatically.

---

## Git-Backed History

Every save auto-commits. Cabinet wraps git operations in `src/lib/git.ts`:

```typescript
// Auto-commit on every page save (Cabinet handles this internally)
// To access history via the UI:
// 1. Open any page
// 2. Click the history icon in the toolbar
// 3. Browse diffs and restore any version

// To inspect from the shell:
cd data
git log --oneline
git diff HEAD~1 HEAD -- my-project/research.md
git checkout HEAD~5 -- my-project/research.md  # Restore older version
```

---

## Markdown Page Format

Cabinet pages are standard markdown files with optional frontmatter:

```markdown
---
title: Competitor Analysis
tags: [research, competitors, q2-2026]
created: 2026-04-07
agent: research-scout
---

# Competitor Analysis

## Summary

...

## Last Updated by Agent

<!-- Agent appends updates here -->
```

---

## API Routes

Cabinet exposes Next.js API routes under `src/app/api/`:

```typescript
// Read a page
GET /api/pages?path=my-project/research

// Save a page
POST /api/pages
Body: { path: "my-project/research", content: "# Research\n..." }

// List directory
GET /api/files?dir=my-project

// Run an agent manually
POST /api/agents/run
Body: { agentId: "research-scout" }

// Get agent status
GET /api/agents/status?id=research-scout

// Search all pages
GET /api/search?q=competitor+analysis
```

### Example: Calling the API from TypeScript

```typescript
// Read a knowledge base page
const response = await fetch('/api/pages?path=my-project/research')
const { content, path } = await response.json()

// Save a page
await fetch('/api/pages', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    path: 'my-project/research',
    content: '# Research\n\nUpdated content...'
  })
})

// Trigger an agent run
await fetch('/api/agents/run', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ agentId: 'research-scout' })
})
```

---

## Zustand State Management

Cabinet uses Zustand stores in `src/stores/`. Key patterns:

```typescript
// Access the page store in a component
import { usePageStore } from '@/stores/pageStore'

function MyComponent() {
  const { currentPage, savePage, pages } = usePageStore()

  const handleSave = async (content: string) => {
    await savePage({ path: currentPage.path, content })
  }

  return <div>{currentPage?.title}</div>
}

// Access agent store
import { useAgentStore } from '@/stores/agentStore'

function AgentPanel() {
  const { agents, runAgent, agentStatus } = useAgentStore()

  return (
    <ul>
      {agents.map(agent => (
        <li key={agent.id}>
          {agent.name} — {agentStatus[agent.id]}
          <button onClick={() => runAgent(agent.id)}>Run</button>
        </li>
  

Related in General