[ AxiomCore · Documentation ]
Run a backend locally
Run an Acore backend on your machine with real actions, reload, mocks or full server simulation, and inspect what the runtime enforces.
Run your backend's real actions on your machine. Local commands need no Axiom account, and real serving never falls back to mocks or Cloud data.
Choose a command
| Goal | Command |
|---|---|
| Run backend source with real actions | axiom run main.acore --deployment deployment.json |
| Run source that has storage mappings, with a local database | axiom run backend/sqlite.acore |
| Serve source or a compiled artifact | axiom serve [INPUT] |
| Serve compiled artifacts on an explicit listener | axiom server run CONTRACT PLAN --deployment FILE |
| Reload source on every edit | axiom serve SOURCE --watch or axiom server dev SOURCE --deployment FILE |
| Check configuration without opening a listener | axiom server validate CONTRACT PLAN --deployment FILE |
| Simulate business logic inside the real server boundary | axiom serve SOURCE --mock, axiom run SOURCE --mode mock, or axiom mock SOURCE |
| Serve contract-level endpoint mocks | axiom mock contract.acore --profile contract |
| Use mocks from a linked Cloud project | axiom mock --cloud |
axiom run is the general runner. For a backend .acore source it defaults
to --mode service, which is the same real serving as axiom serve. For
frontend sources and .axiomapp packages it keeps its target behavior and
rejects backend options such as --mode, --deployment and --fixtures.
Run from source
From a directory that contains main.acore and its AxiomDeps.toml:
axiom check main.acore
axiom build main.acore --out backend.axiom
axiom server deployment backend.axiom backend.server.json --output deployment.json
axiom run main.acore --deployment deployment.json --port 8081Review deployment.json before you run: it lists providers, authentication and
grants, and starts with no grants. The same service can be started in these
equivalent ways:
axiom serve main.acore --deployment deployment.json --port 8080
axiom serve backend.axiom --plan backend.server.json --deployment deployment.jsonOption (serve, run) | Default and rules |
|---|---|
INPUT | serve: .acore source or .axiom artifact, default axiom.acore. run: .acore source |
--deployment | Adjacent deployment.json; never discovered in a parent project |
--plan | serve with an artifact only; defaults to the adjacent INPUT.server.json |
--variant | Source input only; an artifact's variant is fixed |
--host, -p/--port | 127.0.0.1, 8080; --port 0 picks a free port (not with --watch) |
--bindings | Hash-bound sandbox implementation references |
--delivery | Durable delivery configuration; see Events, jobs and webhooks |
-d/--debug | Redacted diagnostics; never raw credentials or bodies |
Explicit paths are relative to the directory where you run the command. A source input is compiled in owned temporary storage; checked artifacts, diff baselines, deployments and bindings are never rewritten. Inputs are limited to 16 MiB.
Missing providers, credentials, grants or handlers, and mismatched hashes fail
before the server reports ready. A source with no executable plan and no
declared Python or Go service fails with a hint to choose --mode mock
explicitly. Native actions fail too: the generic CLI cannot register native
symbols. Ctrl-C or SIGTERM starts a drain: readiness returns 503, new
invocations are rejected, bounded in-flight work finishes, and owned providers
close.
Run source with storage mappings
When a backend source contains storage mappings and
you pass no --deployment, axiom run sets up local development
automatically:
unset DATABASE_URL
axiom run backend/sqlite.acore --port 8080The CLI builds the contract into .axiom/contracts/backend.axiom, applies the
linked database schema (a local SQLite file, or PostgreSQL from
--database-url or DATABASE_URL), binds each storage resource and grants its
operations. It prints Development API key: ... and the backend URL. Send the
key in an apikey header. The key maps to one development identity
(local-developer in tenant demo) and is stored with owner-only permissions
under .axiom/database/. Unsetting DATABASE_URL keeps an unrelated database
from being selected.
This automatic mode binds only storage resources. A plan with other providers
needs an explicit, reviewed deployment. A PostgreSQL schema must declare a
managed application login role with a credentialRef. See
Migrations and persistence and the
task app.
Serve compiled artifacts
axiom server run serves an artifact and its plan on an explicit listener.
This template assumes your own service.acore with a file-backed
tasks.lookup resource, a tasks.json file and an API-key registry:
axiom check service.acore
axiom build service.acore --out backend.axiom
axiom server deployment backend.axiom backend.server.json --output deployment.json
export TASKS_FILE="$PWD/tasks.json"
export API_KEYS_FILE="$PWD/api-keys.json"
axiom server validate backend.axiom backend.server.json --deployment deployment.json
axiom server run backend.axiom backend.server.json --deployment deployment.json --listen 127.0.0.1:8080Before validation, edit the scaffold: add the explicit tasks.lookup grant,
the exact provider interface and plan hashes, and a private hashed API-key
registry (format). A scaffold alone grants no resource
authority. Configuration files hold environment variable names; credentials
stay outside the contract and any bundle. server validate runs the real
provider, authentication, capability, grant and handler preflight, cleans up
and exits without opening a listener. server run prints its startup JSON only
after preflight and listener binding succeed. --listen defaults to
127.0.0.1:8080.
In a second terminal, check readiness, then send one allowed and two rejected requests:
curl --fail http://127.0.0.1:8080/_axiom/ready
curl --fail -H 'x-api-key: workflow-local-key-00000001' http://127.0.0.1:8080/tasks/1
curl -i http://127.0.0.1:8080/tasks/1
curl -i -H 'x-api-key: workflow-local-key-00000001' http://127.0.0.1:8080/tasks/0Expect readiness, a validated task, 401 for the missing credential and 400
for invalid input. Guards apply to direct and nested calls too. No public
endpoint supplies deployment authority or disables a guard.
Reload while editing
axiom serve service.acore --deployment deployment.json --watch
axiom server dev service.acore --deployment deployment.json --listen 127.0.0.1:8080Both reload a source-owned managed or sandbox plan. server dev adds
--bindings, --delivery and --poll-ms (default 250).
- Watch requires a fixed loopback address and a nonzero port. The initial deployment and bindings must match the plan exactly.
- Each change snapshots source, deployment and binding bytes together, compiles in a temporary project, and binds the new plan within the existing interfaces and grants.
- Invalid source, incompatible configuration or a failed provider preflight keeps the previous service. A valid candidate starts after the previous listener drains; if it fails to start, the last valid snapshot restarts. An unavailable external provider or credential can also block that restart.
- Reload briefly interrupts the listener. It is not a rolling deployment.
- Deployment file edits are watched. Environment variable changes need a restart.
- Snapshots are limited to 1,024 files, 16 directory levels and 16 MiB (32 MiB including reviewed companions). Build and preflight each have 30 seconds. Install dependencies and resolve locks before you start.
External Python and Go applications use their own reload tooling.
Run a declared Python or Go service
For a source that declares backend(language:, entrypoint:) and no executable
plan, real serving starts the application itself: Python runs
python3 -m uvicorn module:app --host HOST --port PORT, and Go runs
go run ENTRYPOINT with HOST and PORT set. Startup reports
"enforcement":"application-adapter-required". The CLI does not add middleware
or report readiness for that application; install a
framework adapter in the application to enforce the
contract. Deployment and binding files are rejected in this mode.
Mocks and full simulation
Choose a mock profile explicitly:
| Intent | Command |
|---|---|
| Endpoint mock responses from source | axiom mock contract.acore --profile contract |
| Mocks from the linked Cloud project | axiom mock --cloud |
| Simulate a private server API with its guards | axiom serve service.acore --mock --fixtures mock.json --identities mock-identities.json |
The same, through run | axiom run service.acore --mode mock --fixtures mock.json --identities mock-identities.json |
| Reload source and simulation fixtures | axiom mock service.acore --fixtures mock.json --identities mock-identities.json --watch --port 8080 |
axiom mockuses--profile autoby default: full simulation when the source compiles a private plan, contract mocks otherwise.--profile contractrejects a private plan instead of ignoring its authority, andserve --mocknever downgrades to contract mocks.- Real serving rejects
--fixturesand--identities. Simulation rejects real deployments, bindings and delivery files. Identities default to an adjacentmock-identities.json. - Full simulation needs fixtures bound to the exact contract and plan hashes, with typed resource and action replies. Do not rename endpoint fixtures into a private fixture document.
- A successful simulation reload resets state and rotates development credentials; an invalid edit keeps the last valid service. Public type, guard or authority changes need review and a restart.
- Contract scenarios keep their selection strategies, state, docs and reset
controls. Non-loopback contract listeners protect those routes with an owned
sandbox key. Cloud mocks keep authentication and ETag caching, need a linked
project and Cloud session, and do not support
--watch. Contract mocks cannot enforce private actions. Mocks are a development aid, not a replacement for a production server.
See Server simulation for the fixture format and generated credentials, and Mocks for contract mocks.
Inspect and generate interfaces
axiom server inspect backend.axiom backend.server.json
axiom inspect backend . --format json
axiom server openapi backend.axiom backend.server.json --output openapi.json
axiom server types backend.axiom backend.server.json --language python --output handlers.py
axiom server types backend.axiom backend.server.json --language go --output handlers.goserver inspect validates the exact contract identity and reports effective
guards and policies, action programs, implementation kind (managed, native
or sandbox), nested effects, dependencies and source provenance. Declared
facts stay labeled declared; a verified hash does not make them runtime
evidence. A managed action that calls opaque native code keeps an incomplete
effect summary. Invocation traces separately report what the running host
observed or enforced.
server openapi writes OpenAPI 3.1 and server types writes Python or Go
handler input and output types. Both require a new output path. Generated Go
types also include typed stream frame and message aliases.
Startup prints a private, mode 0600 sessionFile. Pass it with the matching
artifacts to axiom inspect server backend.axiom backend.server.json --session PATH --format json
to see the selected mode and implementation and provider categories. Without
it, the mode is not-observed. This local startup record does not capture
requests or certify production internals. Shutdown deletes it. Inspector keeps
declared facts, local startup observations and unknown production internals
separate.
Sandbox actions
An action can run a verified WebAssembly extension export
through sandbox(extension:, export:). Rust compiles to WebAssembly,
TypeScript runs through Javy, and Python uses the portable ahead-of-time
subset; none starts an unrestricted interpreter. Each needs a signed release,
a verified module identity and a pinned authority lock. Pass
--bindings bindings.json to validation, serving and packaging. Today the
server sandbox denies every external host operation; see
Execution plan for its limits.
Packages that export the standard Invocation to GuestMessage envelope
describe the transport ABI; the host still validates the concrete action input
and completed payload. A package that declares concrete payload type names must
match the action. The
implementation language never implies that a package's effects are proven.
Typed provider setup
Private provider scaffolds include typed configuration digests, reference names and empty grants. Choose a compatible factory and supply every required reference before readiness. Public configuration uses a separate field and audience projection. The default environment resolver reads references once at startup; file and vault resolvers and stronger rotation need qualified trusted implementations. For purpose-bound credentials, see Secrets at runtime.
Test the running host
Test the real request path as well as the generated interfaces. Cover authentication, grants, typed output, cancellation and cleanup. A test clock controls only the boundary it replaces; JWT and session expiry, action deadlines, cache clocks and Redis time need their own real checks. A passing local run does not certify a deployment.
The playground Managed · local server example is editable and inspectable. It names its external runtime requirement, disables browser mock execution and application export for private plans, and shows private guards as unavailable and production internals as unknown. Its source download includes setup helpers for real and full-mock CLI runs.
Next steps
Backend declarations
Reference for the Acore declarations that define backend models, entities, endpoints, actions, typed failures, storage mappings and route groups.
Identity and policies
Verify callers, enforce mandatory guards, and apply CORS, rate limits and idempotency at the Acore server boundary.