Skip to main content

Separan

Separan

Structure should be named, not guessed.

Free programmers from indentation and bracket ambiguity.

AI may write the code. Humans still need to understand it.

日本語 | English

Release PyPI VS Code Marketplace

Separan makes AI-written code easier for people to read, understand, and review. Labels turn otherwise anonymous control flow into visible intent: :validate_payment, :write_audit_log, and :retry_connection become part of the program's checked structure. A reviewer can understand what a block is for, navigate its exact boundary, and verify where an AI made changes without first reconstructing indentation or counting brackets.

Download native builds

The easiest way to try Separan is to download the native release bundle for your platform:

  • Windows installer: separan-installer.exe
  • Windows portable ZIP: separan-portable.zip
  • Linux portable tar.gz: separan-linux-x86_64.tar.gz

Available from the latest GitHub release.

Separan is a multi-implementation language runtime. The Python package and the native C build are both first-class, standalone implementations of the same language specification.

Neither implementation is a reduced fallback or compatibility layer. Both are intended to provide the same public semantics for execution, validation, and language tooling, with the C build optimized for native packaging and the Python build optimized for developer workflows and reference behavior.

The canonical callable unit is SEP (Separate Logic): it is the named logic boundary of a Separan program, written explicitly as a checked structure rather than an implicit Python-style def.

SEP:process_payment
@billing
@payment

if user.active :active_user
charge_card(user.card)
log_success(user.id)
endif:active_user

END_SEP:process_payment

The block name gives the behavior a real identity, and the matching END_SEP closes exactly the same logical boundary. That makes the code easier to review, trace, and verify than a typical indentation-driven function body.

This is not only about restricting AI. It is about making generated code explain its structure to the human who remains responsible for it.

Native CLI in 30 seconds

Download the release bundle for your OS, extract it, and run the binary directly:

# Windows
separan.exe examples/hello.sep

# Linux
./separan examples/hello.sep

Both implementations are intended to be equal citizens of the Separan platform. The Python build provides the developer-oriented reference runtime, and the C build provides the native packaged implementation. They share the same structural language model and are designed to converge on the same public semantics.

Try it in five minutes

First, run a valid labeled block:

if true :check
print "ok"
endif:check

Then run the intentionally broken example:

python -m separan examples/label_mismatch.sep

The closer names a different structure:

if true :check
print "ok"
endif:wrong

Separan points to the structural mistake and tells you the exact closer it expected:

SEPARAN E104: Block label mismatch

 --> demo.sep:3:7
  |
3 | endif:wrong
  |       ^^^^^

The closing or branch label must match its opening block.

Expected:
endif:check

Actual:
endif:wrong

Opened here:
 --> demo.sep:1:10
  |
1 | if true :check
  |          ^

That diagnostic is the language in miniature: structure is named and verified, not inferred from indentation or bracket counting.

Separan is a label-structured scripting language designed for code that humans, AI systems, and development tools can inspect without guessing where a block ends. Indentation is decoration. Every block carries an explicit identity, and its opener and closer must agree.

Design note: the conceptual callable unit is SEP (Separate Logic). The canonical shape is SEP:name / END_SEP:name, because it makes the meaning of a reusable logic unit explicit in the syntax itself.

This is a named logic boundary that describes a separate, independently scoped unit of behavior. In practice, it is the named boundary for Separan, and the syntax stays explicit and structural: SEP:name opens the unit and END_SEP:name closes it.

Variables may use inferred or explicit fixed types. Explicit declarations always include an initializer, so a forgotten value cannot silently become an uninitialized binding:

number retry_count = 0
string service_name = "api"
list<number> samples = []
string optional_note = EMPTY

EMPTY keeps the declared type while removing only the current value. Test the state explicitly with value is EMPTY; a normal operation on an EMPTY value is an error rather than an implicit default.

SEP:main
name = "Separan"

if name is not EMPTY :名前あり
print "Hello, " + name
endif:名前あり

END_SEP:main

Block and multiline-comment labels accept NFC-normalized Unicode identifiers. Program identifiers such as variables and function names remain ASCII-only.

Separan rejects structural mistakes before they can silently succeed:

if user.active :active_user
print "active"
endif:admin_user
SEPARAN E104: Block label mismatch

 --> demo.sep:3:7
  |
3 | endif:admin_user
  |       ^^^^^^^^^^

The closing or branch label must match its opening block.

Expected:
endif:active_user

Actual:
endif:admin_user

Opened here:
 --> demo.sep:1:17
  |
1 | if user.active :active_user
  |                 ^

The 30-second demo

Separan gives a meaningful name to the structure an AI is allowed to edit:

if user.active :active_user
print "active user"
endif:active_user

Give the AI a structural instruction instead of a line-number range:

Modify only Separan scope SEP:main#1/if:active_user#1

The parser verifies that the opening and closing structure agree. The v0.4 review tool extends that identity to the diff boundary:

PASS: AI edit scope verified.
Allowed changes 1, violations 0

The label is simultaneously human documentation, parser-checked structure, and a machine-verifiable edit boundary.

Logic tags add a second, semantic dimension when related code is separated:

SEP:send_notification
@notification
@aws
send_message()
END_SEP:send_notification

@notification is AST metadata, so tools can enumerate the exact logic set instead of asking an AI to guess what “notification-related” means.

separan-structure diff before.sep after.sep
separan-structure verify before.sep after.sep --allow active_user
separan-structure inspect . --tag notification
separan-structure verify before.sep after.sep --allow-tag notification

Use --json for CI and review bots. The VS Code v0.4 extension can compare the active file against Git HEAD and verify the label under the cursor. See the structural AI workflow.

v1.0.0

The current Python reference implementation includes strict label validation, detailed diagnostics, fixed inferred types, homogeneous lists, functions, main auto-start, conditionals, loops, #/## comments, strict escaped and raw strings, semantic tag metadata, and AST output. The v0.4 tooling layer adds a dependency-free LSP, rich VS Code support, structural diffs, and enforced AI edit scopes without changing v0.1 language semantics.

The standard library now covers explicit type conversion, Unicode string and homogeneous-list processing, immutable bytes, datetime and duration values, reproducible and secure randomness, filesystem and process utilities, HTTP client/server previews, authentication, capability-gated mail, YAML/XML structured data, cookies, parameter-bound SQLite, native interface/DHCP/DNS/TCP/UDP networking, capability-checked embedded board profiles, and Pico/Pico 2 C++ firmware generation with Pico SDK ELF/UF2/HEX builds. Built-ins use the same strict argument and type diagnostics as named logic blocks; implicit coercion remains forbidden.

The independent native C runtime is checked against the Python reference by the cross-implementation conformance suite. Its public validation API exposes structured diagnostics for syntax, block, declaration, import, tag, and HTTP route errors, while retained runtime instances expose the last structured failure through the native diagnostic API. The current repository suite has 2,144 collected tests, with 2,141 passing and 3 integration tests skipped when their external database is unavailable.

The published VS Code extension is separan-language 1.0.1. It provides local language intelligence, native diagnostics, structural review workflows, semantic-tag navigation, CodeLens, Call Hierarchy, and Extension Host tests without a Python Language Server dependency.

This release also adds the experimental AWS Lambda runtime: host JSON is converted to immutable Separan values, parsed applications are cached across warm invocations, explicit aws_* adapters form the capability boundary, and separan lambda-package builds Linux-compatible ZIP artifacts. The monitor sample now keeps its Lambda routing, suppression, and state decisions in Separan source.

Native LAN, Wi-Fi, DNS, TCP, and UDP

The 1.0.0 reference runtime provides a capability-gated native network layer for desktop and server scripts. It uses dedicated ip_address, network_interface, tcp_connection, and udp_socket values rather than passing ambiguous strings through every operation.

SEP:main

@network
@diagnostics

interfaces = network_interfaces()

for interface in interfaces :show_interfaces
print interface.name
print interface.kind
print interface.connected
print interface.ip_address
endfor:show_interfaces

END_SEP:main

Run the inspection sample with explicit host permission:

separan examples/network.sep --allow-network-inspection

DNS returns every validated address deterministically. TCP and UDP return bytes, so decoding remains explicit:

addresses = dns_resolve("example.com")

connection = tcp_connect(
    "example.com",
    80,
    timeout = duration("5s")
)

tcp_send(connection, "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n")
reply = tcp_receive(connection, 65536)
print string_from_bytes(reply)
tcp_close(connection)

DHCP, static addressing, and IPv4 link-local are one common IP layer shared by Ethernet and Wi-Fi adapters:

SEP:main

lan = ethernet_open()
network_use_dhcp(lan)

if network_wait_until_addressed(lan, duration("10s")) :address_ready
print network_ip_address(lan)
else:address_ready
print "DHCP failed"
endif:address_ready

END_SEP:main

Embedded adapters can now expose Wi-Fi AP, IPv4 DHCP-server, and simple local DNS-server services without confusing them with the DHCP client API. AP passwords require the redacted secret type, DHCP pools are bounded and validated before startup, and captive-portal DNS behavior is explicit:

wifi = wifi_open()
setup_password = secret_from_environment("SEPARAN_SETUP_PASSWORD")
wifi_start_access_point(wifi, ssid = "Separan-Device", password = setup_password, channel = 6)

dhcp = dhcp_server_start(wifi, server_address = "192.168.4.1", prefix = 24, pool_start = "192.168.4.10", pool_end = "192.168.4.50", gateway = "192.168.4.1", dns_servers = ["192.168.4.1"], lease_time = duration("1h"))

The runtime API and adapter validation are implemented; Pico W/ESP32 adapters still need to connect the contract to lwIP/Pico SDK/ESP-IDF. See the AP/DHCP/DNS sample and network specification.

Network inspection, address configuration, outbound destinations, private-address access, and UDP binding are separate host capabilities. Configuration requires --allow-network-configuration and an explicit adapter; the default native inspector never escalates privileges or invokes a hidden system configurator. See the native network specification.

One source, multiple embedded boards

The embedded preview describes Raspberry Pi Pico/Pico W/Pico 2/Pico 2 W and Arduino Nano/Nano Every through reviewed board profiles. Firmware backends and deployment remain deferred; the portable Blink example documents the intended board-independent source shape and names the board LED instead of copying a physical pin number:

SEP:main

@embedded
@gpio
@sample

gpio_set_mode(pin.LED_BUILTIN, "output")

while true :blink_loop
gpio_write(pin.LED_BUILTIN, true)
delay_milliseconds(500)
gpio_write(pin.LED_BUILTIN, false)
delay_milliseconds(500)
endwhile:blink_loop

END_SEP:main

The source is designed to stay identical when a supported firmware backend is connected; the build targets remain preview scaffolding for now:

separan build examples/embedded/01_blink.sep --board raspberry_pi_pico
separan build examples/embedded/01_blink.sep --board raspberry_pi_pico_2

Each build emits a reviewable C++/CMake project and requires ELF, UF2, and HEX outputs. Install the official Raspberry Pi Pico VS Code extension or pass the SDK/tool paths explicitly. --emit-only generates without compiling, and --validate-only keeps Pico W and Nano profiles available without pretending that they already have firmware backends.

BOOTSEL deployment is explicit and refuses an unrecognized directory:

separan flash build/01_blink-raspberry_pi_pico/build/separan_app_01_blink.uf2 --device E:\

pin.LED_BUILTIN resolves to GPIO25 for both non-wireless firmware targets. Pico W CYW43 control and Arduino Core generation remain pending rather than silently using an incorrect GPIO or backend.

The official embedded examples now cover portable Blink, button input, PWM fade, analog input, UART echo, and I²C scanning. The separate 01_blink_d13.sep example is intentionally board-specific: use pin.LED_BUILTIN for portable code and pin.D13 only when the target profile defines D13 with the required capability.

Higher-order collection processing uses explicit function values: map, filter, and initial-value-required reduce preserve strict callback contracts. One-level flatten, sum, average, and value count complete the core aggregates. Readable mathematics includes explicit root/log names, statistics, moving averages, base conversion, and grouped binary/octal/hexadecimal literals, with domain errors instead of silent NaN/Infinity results.

String processing includes trim, upper, lower, contains, starts_with, ends_with, split, join, replace, code-point-based substring/char_at, UTF-8-byte-bounded clip_utf8, non-overlapping literal find_all, and a string/list-shared reverse.

The experimental temporal implementation provides distinct datetime, local_datetime, timezone, and duration values. It requires explicit zones, rejects ambiguous DST wall times, and keeps Unix units visible in function names. Run separan --timezone-version to inspect the active timezone database.

Randomness is split by purpose: seeded random_* functions use a reproducible language-defined PCG32 stream, while secure_random_* functions use the operating system's cryptographic source. Secure bytes have a distinct bytes type rather than masquerading as a number list.

Binary values are immutable and never convert to strings implicitly. Explicit UTF encodings, strict hex/Base64 codecs, slicing, byte lookup, and binary concatenation are available in the reference preview.

Authentication and cryptography use safe-purpose APIs rather than user-built cipher constructions. Host-provided secrets are a distinct automatically redacted type; HTTP auth, OAuth client credentials, HMAC, HS256 JWT, and Argon2id password hashing have experimental reference implementations.

client_secret = secret_from_environment("OAUTH_CLIENT_SECRET")
token = oauth_client_credentials("https://auth.example.com/oauth/token", "monitor-client", client_secret, scope = "monitor.read")
response = http_request(api_url, auth = bearer_auth(token.access_token))

OAuth token exchange is HTTPS-only, keeps access tokens redacted, and accepts only explicit Bearer responses. Interactive browser login remains a separate future subsystem.

The cryptography preview adds SHA-2/SHA-3 digests, SHA-256/SHA-512 HMAC, explicit bytes-to-hex/Base64 conversion, constant-time comparison, Argon2id key derivation, and versioned AES-256-GCM authenticated encryption. Keys cannot be strings, nonces are generated internally, decrypted secrets remain redacted, and obsolete or unauthenticated ciphers are omitted.

The mail preview composes provider-independent UTF-8 messages with To/Cc/Bcc, text/HTML bodies, file or bytes attachments, and inline content. An explicit sender selects verified STARTTLS/implicit-TLS SMTP or optional Amazon SES; credentials stay secret, Bcc never enters MIME headers, and a separate host capability controls mail delivery and address allowlists.

The structured-data preview adds strict YAML 1.2-style data conversion and a separate XML document model. YAML preserves object order, rejects duplicate keys and heterogeneous sequences, and supports multi-document streams. XML keeps elements, attributes, namespaces, and text explicit while rejecting DTD and entity declarations by default.

HTTP supports one-shot cookies and explicit stateful Cookie Jars. Cookie values, jar display, and received response cookies are redacted; domain, path, expiry, and Secure attributes control transmission.

Lists are homogeneous and zero-based. Value transforms such as list_append, the two-argument list_remove, slice, reverse, and every sort return new lists. The v0.2 preview separately exposes explicit mutating shape operations: EMPTY clears a value, EMPTYS preserves and clears a complete jagged shape, and list_insert/three-argument list_remove add or remove typed slots. See the list specification, shape operations, and runnable example.

length(value) and is_empty(value) work consistently across strings, lists, and bytes. String search, repetition, and padding operate on Unicode code points; failed index_of and last_index_of searches return typed EMPTY values.

const name = value creates an immutable binding while ordinary assignment remains mutable. Labeled object/list data blocks, namespaced imports, capability-based I/O, explicit JSON boundary conversion, and labeled try/catch/finally handling are all available experimentally in the reference interpreter.

The accepted HTTP design keeps http_get lightweight and puts detailed status, headers, and bytes in http_request. It explicitly does not impersonate a browser: JavaScript, DOM, viewport, and navigator state belong to a future browser_open subsystem. The reference preview implements both APIs behind an explicit network capability with host, scheme, port, redirect, timeout, and body-size checks. Labeled HTTP routes and a separately capability-gated development host are also available as a server preview. The dispatcher is transport-independent so a future Lambda or production adapter can reuse the same .sep application. The database preview separates its common API from official SQLite, PostgreSQL, MySQL, Oracle, and Microsoft SQL Server adapters. SQLite is built in; the other four are optional extras. Safe ? placeholder scanning, strict single-row and scalar APIs, labeled transactions, common metadata, and redacted connections are available. Stable execution metadata is available through the reserved read-only system context; dynamic values such as time, requests, randomness, and database state remain explicit functions or scoped values.

The v0.5 Structure Explorer turns the active .sep file into a navigable block tree. Each named structure shows its direct parameters, reads, writes, and calls, plus added/modified/removed state against Git HEAD. Selecting a block jumps to its opener; moving the cursor tracks the deepest enclosing scope. The analysis is parser-backed and never executes the program. See the Structure Explorer specification.

The Language Server preview is available as separan-lsp. It provides parser and simple fixed-type diagnostics, mismatch Quick Fixes, typed Semantic Tokens, Hover, definition, scope-safe label rename, matching highlights, completion, signature help, inlay hints, labeled symbols/folding, and AST-preserving formatting. See the VS Code/LSP specification.

The strict operator set includes power, integer floor division, EMPTY fallback, compound assignment, and typed membership. See examples/operators.sep and the language specification.

External commands follow the same explicitness rule: exec passes a program and argv directly, exec_checked turns nonzero exit into a catchable error, and the separately gated shell_exec is the only API that interprets shell syntax. These process APIs now have an experimental capability-gated implementation.

The utility implementation provides versioned Unicode regexes, deterministic capability-gated glob, process-scoped environment access, and command-line helpers that keep script_path() separate from command_args(). An experimental implementation of these APIs and named function arguments is available in the reference interpreter.

Labeled object:name and list:name data blocks, user.name member access, namespaced imports, and labeled try/catch/finally/throw also have experimental reference implementations.

Deployable monitoring sample

The Separan Monitor sample now includes one upload-ready CloudFormation YAML for up to five EC2 instances and five RDS DB instances. Its inline notify, log2, status, and config-bootstrap Lambda programs connect CloudWatch alarms, Windows/RDS logs, EventBridge state events, Email/SMS/Teams delivery, S3 suppression schedules, and 30-day DynamoDB history. The upload-ready YAML embeds the Separan application and its minimal Lambda runtime, while the readable .sep application source remains in the repository.

python -m pip install -e .
separan examples/hello.sep
separan --ast examples/if.sep
python -m unittest discover -s tests -v

The suite currently contains more than 1,900 tests. Its dedicated negative conformance corpus checks syntax, structure, type and runtime failures, plus too few, too many, and unknown named arguments across every registered built-in.

Python 3.10 or newer is required.

Repository

Separan/
├─ spec/        Language specification
├─ reference/   Python reference implementation
├─ tests/       Conformance and diagnostic tests
├─ examples/    .sep programs
├─ vscode/      VS Code extension
├─ docs/        Philosophy and AI integration
├─ logo/        Official Separan logo and mark
├─ ROADMAP.md
└─ LICENSE

Brand assets are available as the full Separan logo and square Separan mark. The display-ready PNG logo uses compact outer spacing, while a separately optimized 128px derivative is used as the VS Code extension icon.

Read the language specification, the design philosophy, the AI integration model, the temporal-type specification, and the roadmap. The experimental database standard documents the common API and official SQLite, PostgreSQL, MySQL, Oracle, and SQL Server adapters. The reserved system context defines normalized, read-only execution metadata and its namespace boundary. The experimental embedded board mapping adds reviewed logical-pin profiles for Raspberry Pi Pico/Pico 2 and Arduino Nano/Nano Every, plus static validation and preview firmware-generation scaffolding. Firmware backends and deployment remain deferred.

Status

Separan core language and stable standard-library behavior are released as v1.0.0. Features explicitly marked preview or experimental remain outside the stable compatibility promise. The core syntax, diagnostics, and cross-implementation conformance contract are now frozen.

License

Separan is licensed under the Apache License 2.0. See NOTICE for attribution information.

Release files for separan 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for separan 1.0.0
File Size Uploaded
separan-1.0.0.tar.gz 274.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for separan 1.0.0
File Interpreter ABI Platform
separan-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 481.6 kB

Release files / separan-1.0.0.tar.gz

Download URL separan-1.0.0.tar.gz
Size 274.5 kB
Tags Source
SHA-256 checksum
How to use checksums
a138d8519137416f30c61c94ef8a3dc0ec67612c92663c9be3425e17c88158c6
BLAKE2b-256 checksum
How to use checksums
4fe298e4252e0bc9331aa2dbd2aa1a4187c0f99e79f7604d9a8008ea2eb6efe4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 26, 2026.

Transparency log

Release files / separan-1.0.0-py3-none-any.whl

Download URL separan-1.0.0-py3-none-any.whl
Size 207.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6ee2fe9ad8f408b1fc5c6fa1e6396a80e00272192036de3b25c8d0b7875096ae
BLAKE2b-256 checksum
How to use checksums
a7650c81f6713058f1590278d16fd211ad3c5df7c01ba13691d91fa784051dd1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 26, 2026.

Transparency log
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page