Acton is an actor-based programming language with distributed computing capabilities. This guide helps AI assistants understand the codebase structure and development practices.
make # Build everything
make dist/bin/acton # Build only the compiler (faster when working on compiler)
make test # Run all tests
make test-compiler # Run compiler tests only
dist/bin/acton build # Build an Acton project
dist/bin/acton test # Test an Acton projectdist/bin/acton- The Acton compiler and CLI (project management, testing)dist/bin/actonc- Compatibility symlink toacton
acton/
├── compiler/ # Haskell-based compiler → [See compiler/CLAUDE.md]
├── base/ # Standard library & RTS → [See base/CLAUDE.md]
├── backend/ # Distributed runtime → [See backend/CLAUDE.md]
├── ecolift/ # Ecosystem lift process → [See ecolift/CLAUDE.md]
├── test/ # Test suites
├── docs/ # Documentation (mdBook)
└── build.zig # Main build configuration
For detailed information about each component, see:
- compiler/CLAUDE.md - Haskell compiler architecture, compilation pipeline
- base/CLAUDE.md - Standard library modules, RTS, builtins
- backend/CLAUDE.md - Distributed database, actor persistence
- ecolift/CLAUDE.md - Ecosystem lift process for external repositories
- Actors are concurrent entities with private state
- Communication via asynchronous message passing
- No shared memory between actors
- Actors can be distributed across nodes
- Static typing with type inference
- Python-inspired syntax
- Support for generics
- Protocol-based polymorphism (similar to interfaces)
# Variables and functions: snake_case
def calculate_sum(values: list[int]) -> int:
return sum(values)
# Classes and types: PascalCase
class DataProcessor:
def process(self, data: str) -> None:
pass
# Actors: PascalCase
actor WorkerActor:
def handle_request(self, req: Request) -> None:
pass
-- Functions: camelCase
parseExpression :: Parser Expression
-- Types: PascalCase
data AstNode = Literal Int | Variable String
-- Explicit type signatures always
-- 2-space indentation for some functions
-- "Whiteboard layout" for other functions where very deep indent is used to lay out expressions almost like one would when writing beautiful math expressions on a whiteboard// Functions: snake_case with module prefix
int rts_actor_create(rts_actor_t *actor);
// Macros/Constants: UPPER_CASE
#define MAX_ACTORS 1024
// Structs: snake_case with _t suffix
typedef struct actor_state_t {
// ...
} actor_state_t;- Comprehensive Coverage: Every feature should have tests
- Snapshot Tests: For compiler error messages and output
- Performance Tests: Track performance regressions
- Integration Tests: Test distributed features
- Implement C code in
base/builtin/ - Add Acton interface in
base/src/__builtin__.act - Update compiler type system if needed
- Add tests in
test/builtins_auto/
- Create
.actfile inbase/src/ - Add C extension in
.ext.cif needed - Update
base/Build.act - Add module tests
- Work in
compiler/lib/src/Acton/ - Run
make dist/bin/actonfor quick rebuilds - Add test cases in
compiler/acton/test/ - Update snapshot files if error messages change
- Uses Zig build system (
build.zigfiles) - Integrates Haskell (Stack), C, and Acton compilation
- Supports cross-compilation
- Package management via
Build.actfiles
Makefile- Top-level build orchestrationbuild.zig- Main Zig build configurationcompiler/stack.yaml- Haskell dependencies*/Build.act- Acton package configurations
- Compiler Issues: Enable verbose output with
--debug - Runtime Issues: Use
ACTON_LOG_LEVEL=debug - Actor Issues: Monitor with
actonmonutility - Memory Issues: Built-in GC statistics available
- Follow existing code style in each language
- Add tests for new features
- Update documentation as needed
- Ensure
make testpasses before submitting changes - Keep commits focused and well-described
For detailed development workflow and release procedures, see docs/dev.md
When making commits:
- Do not include AI assistant attribution (no "Generated with Claude", co-authored-by or similar)
- Write commit messages as if you wrote the code yourself
- Focus on what the change does, not how it was created
- Try hard to use short summary messages (< 50 chars)
- NEVER use
git add -Aorgit add .- always add files deliberately - Be careful not to add generated files (like
package.yamlwhich are generated from.intemplates)
-
Create release branch: Use format
release-vX.Y.Z(note thevprefix!)git checkout -b release-v0.26.0
-
Update version files:
version.mk- Update VERSION (this controls the version for the entire project)- Note: Do NOT manually edit
package.yamlfiles - they are generated frompackage.yaml.intemplates
-
Update CHANGELOG.md:
- Add new version section with today's date (format: YYYY-MM-DD)
- Organize changes under: Added, Changed, Fixed, Documentation, Testing/CI
- Add PR links for all referenced PRs at the bottom
- Add version comparison link
-
Create and merge PR:
git push -u origin release-vX.Y.Z gh pr create --title "Release vX.Y.Z" -
After PR merge:
- Create and push tag:
git tag vX.Y.Z && git push origin vX.Y.Z - GitHub Actions will automatically create the release
- Update Homebrew formula if needed
- Create and push tag:
- Always use
release-vprefix for release branches (not justrelease-) - Always use today's date in the changelog (not a future or past date)
- The changelog update process is documented in
docs/dev.md