Files
platform/AGENTS.md
T
2026-02-23 22:52:27 +00:00

9.1 KiB

AGENTS.md

Guide for agentic coding assistants working in the Officer monorepo.

What Is Officer

Officer is an AI-powered intranet server for small and medium businesses. It's a self-hosted platform that gives each team member a personal AI assistant, file storage, terminal, code editor, workspaces, and project management — all under centralized admin control.

Think of it as: a self-hosted, AI-native company intranet where every employee gets their own workspace with shared organizational resources and automation.

Multi-User Architecture

  • Role hierarchy: Member → Admin → Owner → Super Admin
  • Bootstrap flow: First user registers as Super Admin, then invites the team
  • Per-user isolation: Files, sessions, settings, workspaces, and tasks are scoped per user under $DATA_PATH/{email}/
  • Shared org resources: Global tasks/skills/processes, server-level settings (SMTP, AI providers, TTS/STT/OCR), pluggable applications and resources
  • Multi-scope resolution: Tasks, skills, and processes resolve user → global → native (built-in), enabling org-wide shared automation

Core Capabilities

  1. AI Chat — Multi-provider (Claude, OpenCode, Pi-Mono) with sessions, attachments, speech-to-text, slash commands
  2. File Browser — Full filesystem access per user (upload, mkdir, copy, move, delete)
  3. File Viewer — Preview video, images, code, text, markdown
  4. Terminal — WebSocket-based PTY terminal with Docker sandboxing
  5. Code Editor — Monaco-based IDE with file tabs
  6. Projects — Project management with per-project workspace layouts, git init
  7. Workspaces — Customizable panel-based layouts (split, resize, swap, drag)
  8. Automation/Skills/Tasks/Processes — Markdown-based capability definitions with YAML frontmatter
  9. Dev Server — Start/stop project dev servers with auto-port discovery and live proxy
  10. Dashboard Widgets — Clock, weather, pomodoro, daily goals, quick notes
  11. Settings — User preferences, server config, resource management

Quick Start Commands

Development

bun dev              # Dashboard + API server (port 5000)
bun dev:emailer      # Emailer workspace

Building

bun run prebuild              # Run prebuild tasks
bun run build:web             # Build web app
bun run build:dashboard       # Build dashboard
bun run build:editor          # Build editor (app + extension + runtime)

Code Quality

bun format          # Format all files (Prettier, required before commit)
bun format:check    # Check formatting without writing
bunx tsgo           # TypeScript type checking

Note: No automated tests configured yet. Always run bun format before committing.

Project Structure

src/
├── apps/
│   └── officer-web/          # Main web UI (React 19)
│       ├── Screens/
│       │   ├── Authentication/   # Login, verify, reset password
│       │   └── Dashboard/        # All main screens (Home, Files, Chat, Terminal, Projects, etc.)
│       ├── state/                # App-specific state hooks
│       ├── lib/                  # Utilities
│       └── locales/              # i18n translations
│
├── servers/
│   ├── api/                  # REST API (Hono, port 5000)
│   │   ├── auth/             # Authentication (JWT + WebAuthn passkeys)
│   │   ├── users/            # User management (invite, CRUD)
│   │   ├── sessions/         # Multi-provider chat sessions
│   │   ├── workspaces/       # Workspace & project state
│   │   ├── tasks/            # Task definitions (CRUD + chat)
│   │   ├── skills/           # Skill definitions (CRUD + chat)
│   │   ├── processes/        # Process definitions (CRUD + chat)
│   │   ├── file-browser/     # Filesystem access (multi-root)
│   │   ├── terminal/         # WebSocket PTY terminal
│   │   ├── dev-server/       # Project dev server management
│   │   ├── pi/               # AI agent integration
│   │   ├── scrape/           # Web scraping (Playwright)
│   │   ├── upload/           # File uploads
│   │   ├── settings/         # User settings & state
│   │   ├── server-settings/  # Server-wide config (SMTP, AI, TTS, etc.)
│   │   ├── dock/             # Dock configuration
│   │   ├── plans/            # Markdown plans
│   │   ├── task-logs/        # Task execution logs
│   │   └── landing-page-data/# Registration status
│   └── _middlewares/         # Auth, rate limiting, CORS, body parsing
│
├── databases/
│   └── officer_db/           # JSON file-based auth store (users, passkeys, tokens)
│
└── workspaces/               # 13 shared packages
    ├── types/                # Central type re-exports
    ├── definitions/          # Constants, enums (roles, statuses, devices)
    ├── config/               # URL configs, env vars
    ├── helpers/              # cn(), formatters, slug, debounce, queue
    ├── hooks/                # 90+ hooks (useClient, useForm, useAuth, etc.)
    ├── state/                # React Query state hooks (useSettings, useChatSessions, etc.)
    ├── components/           # 89 components (shadcn/ui base + custom)
    ├── officerdev/           # Core workspace/panel framework + 11 built-in apps
    ├── i18n/                 # Internationalization
    ├── injector/             # DOM manipulation for visual editing
    ├── widgets/              # Dashboard widgets (clock, weather, pomodoro, etc.)
    ├── emailer/              # React-email templates + SMTP
    └── sounds/               # Audio feedback library

Path Aliases

  • @/src/apps/officer-web/
  • @@/src/servers/
  • @/components/*src/workspaces/components/*

Tech Stack

  • Runtime: Bun
  • Language: TypeScript 5.9 (strict mode, verbatimModuleSyntax)
  • Frontend: React 19, React Router, React Query, Tailwind CSS, shadcn/ui
  • Backend: Hono framework, JWT auth, WebAuthn passkeys
  • Storage: JSON file-based (auth store + user data), no traditional DB for most data
  • Build: Vite
  • AI: Claude Agent SDK, multi-provider support

Code Style Guide

Imports

Order: types → external → workspace → relative

import type { Experiment } from 'types';
import { useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import { useExperiment } from 'hooks/use-experiment';
import { formatDate } from '../helpers';

Type-only imports required (verbatimModuleSyntax):

import { ActionModals, type ActionModalsTypes } from './ActionModals';
import type { FormEvent } from 'react';

TypeScript

  • Strict mode always — no any
  • Prefer type over interface
  • Colocate prop types with components as named exports
  • Early returns for null/undefined guards
  • Use optional chaining and nullish coalescing: obj?.prop ?? fallback

Functions

  • Arrow functions for simple/one-liners
  • Regular functions for complex multi-line logic
  • Named exports only (never default exports)
  • Extract params type when signature gets long (no multiline params)
export const formatDate = (ts: number) => new Date(ts).toLocaleDateString();
export function calculateStats(data: DataPoint[]) { /* ... */ }

React Components

  • Functional components with named prop types
  • Arrow function syntax
  • No useMemo/useCallback (React 19 compiler handles optimization)
type CardProps = { title: string; onClick: () => void };
export const Card = ({ title, onClick }: CardProps) => <div onClick={onClick}>{title}</div>;

State Management

  • React Query for server state
  • useGlobal() for UI state (backed by query cache, no Context needed)
  • useWorkspacesState() for persistent workspace layouts (server-synced)
  • useQueryState() for URL-synced state
  • usePanelChannel() for inter-panel pub/sub communication
  • Manager pattern for complex hooks — return object with state + methods
  • Derived state — compute in hook, not in components

Naming Conventions

  • Components: PascalCase.tsx (e.g., ExperimentCard.tsx)
  • Everything else: kebab-case.ts (e.g., use-experiment.ts, format-date.ts)
  • Hooks: use-*.ts or useFeatureName.ts

Formatting (Prettier)

  • Semicolons: always
  • Quotes: single (JS/TS), double (JSX)
  • Trailing commas: all
  • Indent: 2 spaces
  • Line width: 120 characters

Error Handling

  • Use try/catch for async operations
  • Include context in error messages (IDs, resource names)
  • Always async/await (never .then() chains)

General Guidelines

  • Database-first approach — schema → API → UI
  • Self-documenting code — clear naming, minimal comments
  • Explicit over implicit — no magic
  • Workspace dependencies — use workspace:*
  • Multi-user aware — always consider user isolation and role-based access when adding features
  • File-based storage — user data lives under $DATA_PATH/{email}/, respect the per-user boundary