Skip to content

Commit 899ea3e

Browse files
committed
Add team and personal instructions support; clean up README
1 parent b4df935 commit 899ea3e

6 files changed

Lines changed: 459 additions & 53 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,6 @@ target
1919
# and can be added to the global gitignore or merged into this file. For a more nuclear
2020
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
2121
.idea/
22+
23+
# Sofos workspace directory (contains sessions and personal instructions)
24+
.sofos/

.sofosrc

Lines changed: 343 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,343 @@
1+
# Sofos - AI Coding Assistant Project Context
2+
3+
## Project Overview
4+
5+
Sofos is a terminal-based AI coding assistant powered by Anthropic's Claude API. It's built in Rust for maximum performance and security. The assistant can read/write files, search code, execute bash commands, and search the web - all within a sandboxed environment.
6+
7+
**Core Philosophy:**
8+
- Security first: All operations are sandboxed to the workspace directory
9+
- Fast and efficient: Native Rust implementation with optional ultra-fast editing via Morph API
10+
- Developer-friendly: Interactive REPL with session persistence and custom instructions
11+
- Transparent: All tool executions are visible to the user
12+
13+
## Architecture
14+
15+
### Key Design Decisions
16+
17+
1. **Dual Session Storage Format** (src/history.rs)
18+
- `api_messages`: Anthropic API format for continuing conversations
19+
- `display_messages`: UI-friendly format for showing conversation history
20+
- This separation ensures Claude sees proper API format while users see original UI
21+
22+
2. **Tool Calling Pattern** (src/repl.rs)
23+
- Assistant returns content blocks (text + tool_use)
24+
- REPL executes tools and collects results
25+
- Results sent back as user message with tool_result blocks
26+
- Recursive handling allows Claude to use multiple tools in sequence
27+
28+
3. **Two-Level Instructions** (src/history.rs)
29+
- `.sofosrc`: Project-level, version controlled
30+
- `.sofos/instructions.md`: Personal, gitignored
31+
- Both appended to system prompt at startup
32+
33+
4. **Sandboxing Strategy** (src/tools/filesystem.rs, src/tools/bashexec.rs)
34+
- All paths validated before operations
35+
- Parent directory traversal blocked (`..`)
36+
- Absolute paths rejected
37+
- Symlinks checked to prevent escape
38+
- Bash commands filtered through blocklist
39+
40+
## Code Organization
41+
42+
### Directory Structure
43+
44+
```
45+
src/
46+
├── api/ # Anthropic API integration
47+
│ ├── client.rs # HTTP client for Claude API
48+
│ ├── morph.rs # Morph Apply API client (optional)
49+
│ ├── types.rs # Message types and serialization
50+
│ └── mod.rs
51+
├── tools/ # Tool implementations
52+
│ ├── filesystem.rs # File operations (read, write, list, etc)
53+
│ ├── bashexec.rs # Sandboxed bash execution
54+
│ ├── codesearch.rs # Ripgrep integration
55+
│ ├── types.rs # Tool definitions for API
56+
│ └── mod.rs
57+
├── conversation.rs # Message history management
58+
├── history.rs # Session persistence + custom instructions
59+
├── repl.rs # Main REPL loop and display logic
60+
├── syntax.rs # Markdown/code syntax highlighting
61+
├── cli.rs # Command-line argument parsing
62+
├── error.rs # Error types
63+
├── session_selector.rs # TUI for session selection
64+
└── main.rs # Entry point
65+
```
66+
67+
### Key Files
68+
69+
**src/api/types.rs**
70+
- Defines Message, ContentBlock, and MessageContentBlock enums
71+
- Handles serialization/deserialization for Anthropic API
72+
- Supports both regular and server-side tools (like web_search)
73+
74+
**src/history.rs**
75+
- SessionMetadata: Preview and timestamps for session list
76+
- Session: Dual storage (api_messages + display_messages)
77+
- DisplayMessage: Enum for user messages, assistant responses, and tool executions
78+
79+
**src/repl.rs**
80+
- Main event loop (run method)
81+
- handle_response: Recursively processes assistant responses and tool calls
82+
- display_session: Reconstructs conversation UI when resuming
83+
- Max recursion depth: 50 (prevents infinite loops)
84+
85+
**src/conversation.rs**
86+
- Manages in-memory message history
87+
- Trims to MAX_MESSAGES (500) to prevent token overflow
88+
- Builds system prompt with features list and custom instructions
89+
90+
**src/tools/filesystem.rs**
91+
- validate_path: Security-critical path validation
92+
- All operations check sandboxing before execution
93+
- File size limit: 10MB to prevent memory issues
94+
- User confirmation required for deletions
95+
96+
**src/tools/bashexec.rs**
97+
- COMMAND_BLOCKLIST: Dangerous commands that are always rejected
98+
- Output size limit: 50MB
99+
- No sudo, no file modifications, no directory changes
100+
- Read-only operations only
101+
102+
## Code Conventions
103+
104+
### Rust Style
105+
- Follow standard Rust idioms and conventions
106+
- Use meaningful variable names (no single-letter except in loops)
107+
- Prefer `Result<T>` over `panic!` for error handling
108+
- Use `?` operator for error propagation
109+
- Keep functions focused and under ~100 lines
110+
111+
### Error Handling
112+
- Custom `SofosError` enum in src/error.rs
113+
- Always provide context in error messages
114+
- Use `map_err` to add context when propagating errors
115+
- Display user-friendly error messages in REPL
116+
117+
### Testing
118+
- Unit tests in the same file under `#[cfg(test)]`
119+
- Use `tempfile::TempDir` for filesystem tests
120+
- Mock API calls in tests (don't require real API keys)
121+
- Test security features thoroughly (path validation, sandboxing)
122+
123+
### Documentation
124+
- Add doc comments (`///`) for public APIs
125+
- Explain "why" not just "what" in complex sections
126+
- Keep comments up-to-date with code changes
127+
- README.md is the primary user documentation
128+
129+
## Security Considerations
130+
131+
**Critical Security Features:**
132+
133+
1. **Path Validation** (filesystem.rs:validate_path)
134+
- Canonicalize paths to resolve symlinks
135+
- Check that canonical path starts with workspace
136+
- Reject parent traversal (`..`)
137+
- Reject absolute paths
138+
- This is the first line of defense - NEVER bypass!
139+
140+
2. **Bash Command Filtering** (bashexec.rs)
141+
- Blocklist of dangerous commands (`rm`, `sudo`, `chmod`, etc)
142+
- No output redirection (`>`, `>>`, `|`, `&`)
143+
- No directory changes (`cd`, `pushd`, `popd`)
144+
- No background execution (`&`)
145+
- Read-only operations only
146+
147+
3. **File Size Limits**
148+
- Read operations: 10MB limit
149+
- Bash output: 50MB limit
150+
- Prevents memory exhaustion attacks
151+
152+
4. **User Confirmations**
153+
- Delete operations require interactive confirmation
154+
- Shows what will be deleted before execution
155+
- User can cancel by declining
156+
157+
**When Adding New Features:**
158+
- Always consider security implications first
159+
- Add path validation for any new file operations
160+
- Update blocklist if adding bash command capabilities
161+
- Test with malicious inputs (path traversal attempts, etc)
162+
163+
## Important Implementation Details
164+
165+
### Session Persistence
166+
167+
**Session File Location:**
168+
- Stored in `.sofos/sessions/{session_id}.json`
169+
- Index file: `.sofos/sessions/index.json`
170+
- Entire `.sofos/` directory is gitignored
171+
172+
### Message Flow
173+
174+
**User sends message:**
175+
1. REPL adds to conversation history as user message
176+
2. Creates API request with all messages + system prompt
177+
3. Sends to Claude API
178+
179+
**Claude responds with tools:**
180+
1. Response contains text + tool_use blocks
181+
2. REPL adds full response (with both text and tool_use) to history as assistant message
182+
3. Executes each tool sequentially
183+
4. Collects all tool results
184+
5. Adds all results as single user message
185+
6. Makes new API request (recursive call to handle_response)
186+
187+
**Important:** Tool results must be in a user message, with tool_use_id matching the original tool_use id.
188+
189+
### Custom Instructions Loading
190+
191+
**Load order (history.rs:load_custom_instructions):**
192+
1. Load `.sofosrc` from project root (if exists)
193+
2. Load `.sofos/instructions.md` from workspace (if exists)
194+
3. Combine with headers ("# Project Instructions", "# Personal Instructions")
195+
4. Append to system prompt
196+
197+
**Display:**
198+
- If either file exists, show "Loaded custom instructions" in green
199+
- Silent if neither exists
200+
201+
### Recursion Depth Limiting
202+
203+
**Problem:** Claude can make infinite tool calls if it gets stuck in a loop
204+
205+
**Solution:** (repl.rs:handle_response)
206+
- Track recursion depth in REPL struct
207+
- MAX_RECURSION_DEPTH = 50
208+
- If exceeded, show warning and stop
209+
- Reset to 0 at start of new user message
210+
211+
### Thinking Animation
212+
213+
When waiting for Claude's response after tool execution:
214+
- Show animated spinner ("⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏")
215+
- Orange color (0xFF, 0x99, 0x33)
216+
- "Thinking..." text
217+
- Clears when response arrives
218+
219+
## Dependencies
220+
221+
### Core Dependencies
222+
- `tokio`: Async runtime for HTTP requests
223+
- `reqwest`: HTTP client for API calls
224+
- `serde`, `serde_json`: Serialization/deserialization
225+
- `colored`: Terminal colors and formatting
226+
- `rustyline`: REPL with readline support
227+
- `clap`: Command-line argument parsing
228+
229+
### Optional Dependencies
230+
- `ripgrep`: Code search functionality (runtime check)
231+
- Morph API: Ultra-fast code editing (via MORPH_API_KEY)
232+
233+
### Why These Choices?
234+
- `tokio` + `reqwest`: Industry standard for async HTTP in Rust
235+
- `rustyline`: Best readline implementation for Rust CLIs
236+
- `colored`: Simple, cross-platform terminal colors
237+
- Native dependencies minimal (only ripgrep, which is optional)
238+
239+
## Testing Strategy
240+
241+
### What to Test
242+
- Path validation with various malicious inputs
243+
- Bash command blocklist effectiveness
244+
- Session save/load with different formats
245+
- Message trimming behavior
246+
- Tool execution and result collection
247+
248+
### What Not to Test
249+
- Actual Claude API responses (too expensive, non-deterministic)
250+
- Actual file I/O in most cases (use TempDir)
251+
- Network requests (mock when possible)
252+
253+
### Running Tests
254+
```bash
255+
cargo test # All tests
256+
cargo test filesystem # Just filesystem tests
257+
cargo test -- --nocapture # Show println output
258+
```
259+
260+
## Common Tasks
261+
262+
### Adding a New Tool
263+
264+
1. Define tool in `src/tools/types.rs` (get_tools or get_tools_with_morph)
265+
2. Implement execution in appropriate file (filesystem.rs, bashexec.rs, etc)
266+
3. Add match arm in `src/tools/mod.rs` (ToolExecutor::execute)
267+
4. Test the new tool thoroughly
268+
5. Update README.md with tool description
269+
270+
### Adding a New API Field
271+
272+
1. Update types in `src/api/types.rs`
273+
2. Add serde attributes for proper serialization
274+
3. Handle in response processing (repl.rs:handle_response)
275+
4. Test with actual API if possible
276+
277+
### Debugging Tool Execution
278+
279+
Set `SOFOS_DEBUG=1` environment variable:
280+
```bash
281+
SOFOS_DEBUG=1 cargo run
282+
```
283+
284+
This prints:
285+
- Recursion depth at each step
286+
- Number of tools being executed
287+
- Tool success/failure and output length
288+
- Conversation state before API calls
289+
290+
## Version Compatibility
291+
292+
### Anthropic API
293+
- Uses Claude Messages API (not legacy Completions)
294+
- Model: claude-sonnet-4-5 (default)
295+
- Supports tool calling and server-side tools (web_search)
296+
- API version: 2023-06-01
297+
298+
### Morph API
299+
- Uses Morph Apply REST API
300+
- Model: morph-v3-fast (default)
301+
- Optional integration via MORPH_API_KEY
302+
- Provides `morph_edit_file` tool when available
303+
304+
## Future Considerations
305+
306+
**Potential Improvements:**
307+
- Streaming responses for faster perceived performance
308+
- Multiple parallel tool executions (currently sequential)
309+
- Richer TUI with panels and split views
310+
- Plugin system for custom tools
311+
- Configuration file for default settings
312+
313+
**Constraints:**
314+
- Keep binary size small (currently ~5MB)
315+
- Maintain zero-setup experience (except API keys)
316+
- Keep security as top priority
317+
318+
## When Working on This Codebase
319+
320+
**Always:**
321+
- Test security features when making changes to filesystem or bash tools
322+
- Update both README.md and this .sofosrc when adding features
323+
- Run `cargo test` before committing
324+
- Add helpful error messages for user-facing errors
325+
326+
**Never:**
327+
- Skip path validation in file operations
328+
- Add commands to bash without security review
329+
- Panic in user-facing code (use Result and show errors gracefully)
330+
- Break the tool calling protocol (tool_use -> tool_result matching)
331+
- Commit API keys or sensitive data
332+
333+
**Code Review Checklist:**
334+
- [ ] Security: Path validation present and correct?
335+
- [ ] Security: New bash commands in blocklist if needed?
336+
- [ ] Error handling: All Results properly handled?
337+
- [ ] Tests: Added tests for new functionality?
338+
- [ ] Docs: Updated README if user-visible change?
339+
- [ ] UX: Error messages clear and actionable?
340+
341+
---
342+
343+
This file is loaded by Sofos and appended to the system prompt, providing deep project context for AI-assisted development.

0 commit comments

Comments
 (0)