JoyBoy is being structured as a public-ready local AI harness with a clear split between:
public corelocal configurationoptional local packs
The public core should stay focused on reusable infrastructure:
- chat and multimodal orchestration
- image/video routing
- model management
- onboarding
- doctor checks
- provider configuration
- UI shell
JoyBoy keeps agent/coding behavior in a reusable public-core layer:
core/agent_runtime/
This layer owns runtime contracts that should not depend on Flask routes or UI state:
- stream event names and schema versions
- tool loop guardrails
- tool output truncation
- host path masking before tool output reaches the model
- local file-backed memory facts for terminal agents
- LLM provider catalog and provider-prefixed cloud model client
- bounded backend-managed subagents for coding workflows:
code_explorerfor read-only codebase contextverifierfor one allowlisted test/build command without shell chaining
Terminal mode can use this runtime today, and future subagents, MCP tools, pack skills, and coding providers should plug into it instead of duplicating tool logic in routes.
Terminal memory is stored outside git in:
~/.joyboy/agent_memory.json
The terminal only writes durable facts through the remember_fact tool and can
retrieve them through list_memory. It must not store secrets, API keys, tokens,
private URLs, or transient task chatter. At the start of a terminal run, JoyBoy
searches this store with the user's request and injects only a few matching
facts as read-only context.
The goal is to keep this surface contributor-friendly and easy to reason about.
Terminal context size is a local Ollama runtime setting, not a promise that every model can actually use the window. The UI exposes 2K through 256K and clamps the backend to the same maximum. Small and default contexts keep the strict per-turn token guard; 64K, 128K, and 256K raise that guard in bounded tiers so larger local windows have a real effect without bringing back unbounded tool loops.
Machine-specific state lives outside git in:
~/.joyboy/config.json
This local config stores:
- provider credentials
- feature flags
- active local packs
- onboarding state
Priority order:
- process environment
.env- local JoyBoy config
LLM cloud providers are optional. The terminal runtime accepts provider-prefixed
model ids for OpenAI-compatible providers, for example openai:gpt-4o-mini or
openrouter:provider/model-name. See docs/LLM_PROVIDERS.md.
Optional capabilities can be loaded from:
~/.joyboy/packs/<pack_id>/
Each pack is validated through pack.json before activation.
Packs can expose:
- router rules
- prompt assets
- model sources
- UI overrides
This keeps the public core lean while still allowing machine-specific extensions.
The frontend should not guess what is available.
Instead:
- backend returns feature flags
- backend returns feature exposure
- UI renders visible, locked, or active surfaces accordingly
This is how JoyBoy can show an optional surface without pretending it is active everywhere.
The recommended install path is:
- start JoyBoy with the platform launcher
- finish onboarding
- check the Doctor
- add providers
- import optional packs or model sources
Onboarding gets a new machine to a usable state quickly. Doctor explains what is missing when the machine is not fully ready.
- keep public APIs explicit
- prefer additive extensions over hidden side effects
- avoid duplicating routing logic
- store secrets locally, never in git
- let the UI reflect backend truth
JoyBoy uses centralized CSS variables defined in:
web/static/css/variables.css
These variables act as design tokens for consistent styling across the UI.
- colors (primary, background, state)
- spacing (layout scale)
- typography (font sizes)
- effects (shadows, transitions, overlays)
This approach keeps styling predictable and easy to extend without modifying component-level styles.