Target Audience: This guide is written for AI agents (like Claude) working on the CodeOSX implementation, but is also useful for human developers.
- Development Philosophy
- Session Workflow
- Task Management
- Decision Making
- Documentation Requirements
- Code Standards
- Testing Requirements
- Git Workflow
- Communication Protocol
- Compatibility First: Every feature must work on Mac OS X 10.0+ or degrade gracefully
- C89 Strict: No C99/C11 features, compile with
-std=c89 -pedantic - Document Everything: Decisions, progress, and rationale must be recorded
- Test Early: Write tests as you implement, not after
- Small Commits: Commit frequently with descriptive messages
- No Regressions: All tests must pass before marking a task complete
- Binary Size Budget: Final binary must be < 200 KB
- Memory Budget: Runtime memory < 5 MB under normal operation
- No Dependencies: Everything bundled (BearSSL, SQLite)
- Cross-Platform: Code must compile for PowerPC, Intel i386, Intel x86_64
Every development session should follow this structure:
# Check current state
git status
git log --oneline -5
# Review active work
cat Documentation/PROGRESS.md | grep "In Progress"
cat ~/.codeosx/todos.json # If using TodoWrite toolMental Checklist:
- What phase are we in?
- What was completed last session?
- What are the active blockers?
- What's the goal for this session?
Use the TodoWrite tool to create/update your task list:
[
{
"content": "Download and integrate BearSSL 0.6 source",
"status": "in_progress",
"activeForm": "Downloading and integrating BearSSL 0.6"
},
{
"content": "Create test_bearssl.c compilation test",
"status": "pending",
"activeForm": "Creating test_bearssl.c compilation test"
},
{
"content": "Verify BearSSL compiles with -std=c89",
"status": "pending",
"activeForm": "Verifying BearSSL compiles with -std=c89"
}
]For each task:
- Mark as in_progress in TodoWrite
- Implement the feature/fix
- Test immediately (unit test or manual verification)
- Commit with descriptive message
- Mark as completed in TodoWrite
After completing tasks:
Update PROGRESS.md:
#### Day 3-7: BearSSL Integration
- [x] Download BearSSL 0.6 source
- [x] Add BearSSL as git submodule
- [x] Create test_bearssl.c
- [x] Compile BearSSL on modern Mac (macOS 14+)
- [x] Compile BearSSL with -std=c89 -pedantic ✅ SUCCESS
- [ ] Test on Mac OS X 10.7 Lion (no hardware available)If you made a decision, update DECISIONS.md:
## 2026-01-16: BearSSL Version Selection
**Decision**: Use BearSSL 0.6 instead of 0.5
**Rationale**:
- Version 0.6 has better TLS 1.2 support
- Compiles cleanly with GCC 4.2 and Clang 15
- Binary size only 18KB (under budget)
**Alternatives Considered**:
- BearSSL 0.5 (older, potentially more compatible with GCC 2.95)
- OpenSSL (too large, ~2MB)
**Trade-offs**: May need patches for very old GCC 2.95 on Mac OS X 10.0
**Testing**: Compiled successfully on macOS 14 with -std=c89 -pedantic
**Status**: ActiveAdd session log to PROGRESS.md:
### 2026-01-16: BearSSL Integration Session
- **Duration**: 2 hours
- **Completed**:
- Downloaded and integrated BearSSL 0.6
- Created test_bearssl.c
- Verified C89 compliance
- Documented BearSSL decision in DECISIONS.md
- **Next Session**: SQLite integration
- **Blockers**: Cannot test on Lion without hardware (accepted risk)Commit all documentation updates:
git add Documentation/PROGRESS.md Documentation/DECISIONS.md
git commit -m "docs: Update progress and decisions for BearSSL integration"The TodoWrite tool is your primary task tracker during active development.
Task Format:
{
"content": "Imperative form: 'Create config.c with environment variable loading'",
"status": "pending|in_progress|completed",
"activeForm": "Present continuous: 'Creating config.c with environment variable loading'"
}Rules:
- Only ONE task in_progress at a time
- Mark completed IMMEDIATELY after finishing (don't batch)
- Remove obsolete tasks (don't let list grow stale)
- Break large tasks into 2-4 hour chunks
Example Usage:
User: Implement the configuration system
AI Agent:
1. Uses TodoWrite to create task list:
- Create src/config.h header
- Create src/config.c implementation
- Add environment variable parsing
- Add API key validation
- Write unit tests
2. Implements each task sequentially
3. Marks completed in TodoWrite as finished
4. Updates PROGRESS.mdGood Task Size (2-4 hours):
- "Create config.c with environment variable loading"
- "Implement read_file tool with path validation"
- "Write unit tests for JSON parser"
Too Large (needs splitting):
- "Implement entire HTTP client" → Split into: TLS setup, request building, response parsing
- "Build all file tools" → One tool at a time
Too Small (combine):
- "Create config.h" + "Create config.c" → "Implement configuration system"
Document in DECISIONS.md when:
- Architectural choices: BearSSL vs OpenSSL, SQLite version selection
- API design: Function signatures, data structures
- Trade-off decisions: Performance vs compatibility, size vs features
- Tool/library choices: cJSON vs custom parser
- Workarounds: Platform-specific hacks
- Obvious implementations (using POSIX file I/O is standard)
- Temporary debugging changes
- Minor refactoring without functional impact
1. Identify decision point
↓
2. Research options (compile tests, read docs)
↓
3. If multiple valid paths → AskUserQuestion
↓
4. Make decision (or get user input)
↓
5. Document in DECISIONS.md with rationale
↓
6. Implement and test
↓
7. If fails, revisit decision (update status to "Superseded")
When you encounter a decision where user preference matters:
AI Agent: I've researched JSON parser options. We have two good choices:
1. **cJSON** (single-file library)
- Pros: Mature, well-tested, C89 compatible
- Cons: ~2000 lines of code, adds ~8KB to binary
2. **Custom minimal parser**
- Pros: Tiny (~500 lines), only parses what we need
- Cons: More potential for bugs, need to write tests
Both work on Mac OS X 10.0+. Which would you prefer?Then use AskUserQuestion tool to present options formally.
After every significant milestone (completing a phase task):
-
Update PROGRESS.md:
- Mark tasks as complete
- Update completion percentages
- Add session log entry
-
Update DECISIONS.md (if applicable):
- Add decision entry with full template
-
Update CHANGELOG.md (for releases):
- Add features/changes under [Unreleased] section
-
Code Comments:
- Every function needs a comment (purpose, params, return value)
- Complex algorithms need explanation
- Platform-specific hacks need rationale
Function Comment Format:
/*
* Loads configuration from environment variables.
*
* Reads ANTHROPIC_API_KEY, CODEOSX_* environment variables and
* populates the config struct with values or defaults.
*
* @param config Pointer to config_t struct to populate
* @return 0 on success, -1 if API key missing or invalid
*/
int config_load(config_t *config);File Header Format:
/*
* config.c - Configuration management for CodeOSX
*
* Handles loading environment variables, validating API keys,
* and setting default values for all configuration options.
*
* Compatible with: Mac OS X 10.0+ (C89)
*/Before committing code, verify:
- No
//comments (use/* */) - No variable declarations mid-block
- No inline functions
- No
long long(uselongor cast to double if needed) - No
for (int i = 0; ...)(declareiat block start) - No C99 standard library functions (use POSIX equivalents)
- Compiles with
gcc -std=c89 -pedantic -Wall -Wextra -Werror
Formatting:
- Indentation: 4 spaces (no tabs)
- Line length: 100 characters max
- Braces: K&R style (opening brace on same line)
Naming Conventions:
- Functions:
snake_case(e.g.,config_load,http_post_json) - Structs:
snake_case_t(e.g.,config_t,session_t) - Constants:
UPPER_CASE(e.g.,MAX_PATH_LEN) - Macros:
UPPER_CASE(e.g.,ASSERT)
Example:
#define MAX_API_KEY_LEN 256
typedef struct {
char api_key[MAX_API_KEY_LEN];
int max_tokens;
} config_t;
int config_load(config_t *config) {
char *api_key;
/* Get API key from environment */
api_key = getenv("ANTHROPIC_API_KEY");
if (api_key == NULL) {
return -1;
}
/* Copy to config struct */
strncpy(config->api_key, api_key, MAX_API_KEY_LEN - 1);
config->api_key[MAX_API_KEY_LEN - 1] = '\0';
return 0;
}Always check return values:
/* BAD */
fopen("file.txt", "r");
/* GOOD */
FILE *fp = fopen("file.txt", "r");
if (fp == NULL) {
fprintf(stderr, "Error: Cannot open file.txt\n");
return -1;
}Use consistent error codes:
0= success-1= general error-2,-3, etc. = specific error codes (document in header)
For every feature:
- Write test BEFORE or DURING implementation
- Run test to verify it fails (proving it tests something)
- Implement feature
- Run test to verify it passes
- Do NOT mark task complete until test passes
Unit Tests (most common):
/* tests/test_config.c */
TEST(config_validate_api_key_valid) {
ASSERT(config_validate_api_key("sk-ant-test123"),
"Valid key should pass");
return 0;
}
TEST(config_validate_api_key_invalid) {
ASSERT(!config_validate_api_key("invalid"),
"Invalid key should fail");
return 0;
}Integration Tests (shell scripts):
#!/bin/bash
# tests/integration_test.sh
echo "Test 1: Basic API connection"
export ANTHROPIC_API_KEY="sk-ant-test"
timeout 10 ./build/codeosx --test-connection
if [ $? -eq 0 ]; then
echo "PASS"
else
echo "FAIL"
exit 1
fiManual Tests (documented in CODEOSX_TESTING.md):
- Follow manual test checklist
- Document results in PROGRESS.md
# Build and run unit tests
make tests
./build/test_runner
# Run integration tests
./tests/integration_test.sh
# Verify C89 compliance
make clean
gcc -std=c89 -pedantic -Wall -Wextra -Werror src/**/*.cmain- Stable releases only (tagged)develop- Active development (default branch)feature/phase-X-description- Feature branches for major work
<type>(<scope>): <subject>
<body>
<footer>
Types:
feat: New featurefix: Bug fixdocs: Documentation onlytest: Adding or updating testsrefactor: Code refactoringstyle: Formatting changesbuild: Build system changes
Examples:
feat(http): Add BearSSL TLS 1.2 client
Implemented http_client.c with BearSSL integration.
Supports POST requests to Claude API with custom headers.
Refs: Phase 1, Day 4-10
---
docs(progress): Update Phase 0 completion status
- Marked BearSSL integration as complete
- Added session log for 2026-01-16
- Updated metrics
---
fix(config): Handle missing API key gracefully
Previously crashed with segfault if ANTHROPIC_API_KEY was not set.
Now returns error code -1 with clear error message.
Fixes: Issue #12Commit after:
- Each completed task (every 1-2 hours)
- Before switching to a different area of code
- After all tests pass
- End of each session
Do NOT:
- Commit broken code (except on feature branches with WIP prefix)
- Commit without testing
- Make massive commits (> 500 lines changed)
When uncertain, use this template:
**Context**: I'm implementing [feature] in Phase [X]
**Question**: Should I [option A] or [option B]?
**Option A**: [Description]
- Pros: ...
- Cons: ...
**Option B**: [Description]
- Pros: ...
- Cons: ...
**My Recommendation**: [Choice] because [rationale]
**Impact**: This affects [components/timeline/budget]When blocked, immediately document:
**Blocker**: [Description]
**Impact**: Cannot proceed with [task/phase]
**Attempted Solutions**:
1. [What you tried]
2. [What you tried]
**Proposed Resolution**:
- Option 1: [Description]
- Option 2: [Description]
**Timeline Impact**: [Estimate delay]Add to PROGRESS.md under "Active Blockers" section.
At the end of each session:
- Update PROGRESS.md with session log
- Inform user of:
- What was completed
- What's next
- Any blockers or decisions needed
- Provide metrics:
- Lines of code written
- Tests added/passing
- Binary size (if changed)
Session Start:
- Review PROGRESS.md
- Check git status
- Plan tasks with TodoWrite
During Development:
- One task in_progress at a time
- Test each feature immediately
- Commit every 1-2 hours
- Update todos as you go
Session End:
- Mark all completed tasks
- Update PROGRESS.md
- Add session log
- Commit all changes
- Clean up todos.json
- todos.json: Every task change (real-time)
- PROGRESS.md: After each milestone or session
- DECISIONS.md: After architectural decisions
- CHANGELOG.md: Weekly (under [Unreleased])
- Code comments: As you write code
# Verify C89 compliance
gcc -std=c89 -pedantic -Wall -Wextra -Werror src/*.c
# Build and test
make clean && make && make test
# Check binary size
ls -lh build/codeosx
# Run connection test
./build/codeosx --test-connection
# View recent progress
tail -20 Documentation/PROGRESS.md
# Check active todos
cat ~/.codeosx/todos.json | jq .Session Start:
# Review current state
cat Documentation/PROGRESS.md | grep "Phase 1"
# Shows: Phase 1 - In Progress, need to implement config systemPlanning:
// TodoWrite tool
[
{
"content": "Create src/config.h with config_t struct",
"status": "pending",
"activeForm": "Creating src/config.h with config_t struct"
},
{
"content": "Implement config_load() in src/config.c",
"status": "pending",
"activeForm": "Implementing config_load() in src/config.c"
},
{
"content": "Add config_validate_api_key() function",
"status": "pending",
"activeForm": "Adding config_validate_api_key() function"
},
{
"content": "Write unit tests in tests/test_config.c",
"status": "pending",
"activeForm": "Writing unit tests in tests/test_config.c"
}
]Implementation (Task 1):
# Mark in progress
# TodoWrite: Set task 1 to "in_progress"
# Create src/config.h
# (Write config.h with struct definition)
# Verify compiles
gcc -std=c89 -c src/config.h
# Commit
git add src/config.h
git commit -m "feat(config): Add config_t struct definition"
# Mark complete
# TodoWrite: Set task 1 to "completed"Documentation:
# Update PROGRESS.md
# Mark "Create src/config.h" as [x] done
# No decision needed (standard implementation)Session Wrap-Up:
### 2026-01-17: Configuration System Implementation
- **Duration**: 2.5 hours
- **Completed**:
- Created config.h with config_t struct
- Implemented config_load() with environment variable parsing
- Added API key validation
- Wrote 4 unit tests (all passing)
- **Next Session**: HTTP client implementation
- **Blockers**: NoneEnd of Contributing Guide
For questions or clarifications, refer to:
- CODEOSX_IMPLEMENTATION_PLAN.md - Detailed phase breakdown
- CODEOSX_ARCHITECTURE.md - System design
- CODEOSX_TESTING.md - Testing strategies
- DECISIONS.md - Past decisions and rationale