cabinet-ai-knowledge-base
AI-first knowledge base and startup OS with file-based storage, AI agents, scheduled jobs, and embedded apps
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
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.