Development Workflow
This guide explains how to work on Sloppy in development and which repository rules contributors are expected to follow.
Project structure
| Path | Responsibility |
|---|---|
Sources/sloppy | Backend executable, HTTP server, routing, orchestration, config, persistence |
Sources/AgentRuntime | Runtime actors and orchestration for channels, branches, workers, compactor, and visor |
Sources/Protocols | Shared wire models and JSON helpers |
Sources/PluginSDK | Plugin contracts for models, tools, memory, and gateways |
Sources/Node | Node daemon executable (product: SloppyNode) |
Sources/ChannelPluginDiscord | Discord gateway integration |
Sources/ChannelPluginTelegram | Telegram gateway integration |
Dashboard/ | React/Vite frontend |
Tests/ | Swift Testing suites |
docs/ | VitePress documentation, specs, and ADRs |
Development setup
Pick one of the build guides first:
- Build From Terminal
- Build With Docker
- Model Providers — configure LLM providers and API keys
For day-to-day development, direct terminal builds are the default path because they give a faster feedback loop.
Dev script
The repository includes scripts/dev.sh — a single entry point for building, linking, and running the server during development.
Build and link
scripts/dev.sh setupThis builds sloppy and SloppyNode in release mode and creates symlinks in ~/.local/bin so both commands are available on your PATH. You can override the symlink directory:
scripts/dev.sh setup --bin-dir ~/.local/binServer management
| Command | What it does |
|---|---|
scripts/dev.sh start | Start the sloppy server in the background |
scripts/dev.sh stop | Stop the background server |
scripts/dev.sh restart | Stop and start the server |
scripts/dev.sh status | Check whether the server is running |
scripts/dev.sh logs | Tail the server log (/tmp/sloppy-server.log) |
Auto-start
To launch the server automatically whenever a new terminal opens:
scripts/dev.sh autostartThis adds a small hook to your .bashrc (or .zshrc) that starts sloppy run in the background if it is not already running. To remove the hook:
scripts/dev.sh autostart-offsloppy development rules
Architecture boundaries
- Keep transport, routing, services, runtime, and persistence separated.
- Preserve the flow
CoreHTTPServer -> CoreRouter -> CoreService -> AgentRuntime -> SQLiteStore. - Do not collapse multiple responsibilities into one large type when the repository already has a boundary for that concern.
Swift conventions
- Use 4-space indentation.
- Keep imports minimal and put
Foundationfirst when used. - Prefer focused files and small helpers over long monolithic methods.
- Use
structfor DTO-style data andactorfor shared mutable state. - Mark cross-target API as
publicwhen it must be consumed by another target. - Add
Sendablewhen values cross concurrency boundaries. - Avoid force unwraps and
fatalErrorin production code paths.
Concurrency rules
- Prefer actor isolation instead of manual locking.
- Keep async flows
async/awaitend to end. - Do not bypass actor boundaries with shared mutable globals.
- Handle operational failures gracefully and log useful context.
API and runtime behavior
- Keep public behavior backward-compatible unless a change explicitly allows breakage.
- Convert invalid HTTP payloads into stable 4xx responses.
- Prefer concise structured runtime payloads over large opaque blobs.
- Keep branch results concise: return conclusions and references instead of dumping full transcripts.
Frontend conventions
- Use function components and hooks.
- Prefer named exports for components and utilities.
- Keep local state local and derive computed values when helpful.
- Use
async/awaitand handle non-OK responses explicitly. - Match the existing frontend style: 2-space indent, semicolons, and double quotes.
Testing expectations
When behavior changes, update or add tests.
Use Swift Testing:
import Testing@Test#expect
Testing guidance:
- Favor behavior-focused tests with clear arrange / act / assert flow.
- Keep tests deterministic and isolated.
- For endpoint logic, test through router or service layers with realistic payloads.
Validation strategy
Run the smallest relevant checks first, then move to broader validation.
Smallest relevant checks
Examples:
swift test --filter sloppyTests
swift test --filter AgentRuntimeTests
swift build -c release --product sloppyFor dashboard work:
cd Dashboard
npm run buildCI-parity validation
Before opening a PR, run:
swift test --parallel
swift build -c release --product sloppy
swift build -c release --product SloppyNode
cd Dashboard
## Built-in channel config
sloppy can bootstrap built-in channel gateways directly from `sloppy.json`.
Example Discord configuration:
```json
{
"channels": {
"discord": {
"botToken": "discord-bot-token",
"channelDiscordChannelMap": {
"general": "123456789012345678"
},
"allowedGuildIds": ["987654321098765432"],
"allowedChannelIds": [],
"allowedUserIds": []
}
}
}npm install npm run build
## Recommended contribution flow
1. Create a focused branch for one change.
2. Read the surrounding module before editing it.
3. Keep the change small and aligned with existing patterns.
4. Add or update tests if behavior changed.
5. Run the smallest relevant checks.
6. Run CI-parity validation before opening a PR.
## Documentation expectations
- Update `README.md` when the project entry point or positioning changes.
- Update `docs/specs/` when protocol or runtime behavior changes.
- Add or update ADRs when an architectural decision needs durable rationale.
- Keep docs aligned with the actual commands, targets, and files in the repository.