Skip to main content

A lightweight DSL for scaffolding files and folders

Project description

🧱 Bytecraft

A human-readable DSL for scaffolding files and folders.

pip install bytecraft

Bytecraft lets you describe a project structure in plain, readable instructions and execute it with a single command — no Bash, no Python boilerplate, no mental overhead.

# bootstrap.bc

load-vars "project.ebv"

set-working-folder "{{project}}"

make-folder "src"
make-folder "src/utils"
make-folder "assets"

make-file "README.md" with "# {{project}}"
make-file "src/main.py" with "print('Hello, World!')"
make-file "src/utils/helper.py"
py -m bytecraft bootstrap.bc
[Bytecraft] Loaded 3 variable(s) from: project.ebv
[Bytecraft] Working folder set: my-app
[Bytecraft] Created folder: my-app/src
[Bytecraft] Created folder: my-app/src/utils
[Bytecraft] Created folder: my-app/assets
[Bytecraft] Created file: my-app/README.md
[Bytecraft] Created file: my-app/src/main.py
[Bytecraft] Created file: my-app/src/utils/helper.py

Installation

Requires Python 3.10+

pip install bytecraft

Commands

set-working-folder

Sets the base directory for all subsequent relative paths. Created automatically if it doesn't exist.

set-working-folder "my-project"

make-folder

Creates a directory and any missing parent directories. Does nothing if the folder already exists.

make-folder "src/utils"

make-file

Creates a file. Parent directories are created automatically. Overwrites if the file already exists.

# Empty file
make-file "src/__init__.py"

# Inline content
make-file "VERSION" with "1.0.0"

# Multi-line content block
make-file "README.md" with ---
# My Project

Some description here.
---

append-file

Appends content to an existing file. Creates the file if it doesn't exist. A newline is automatically inserted before the new content if the file is non-empty.

make-file "log.txt" with "First entry"
append-file "log.txt" with "Second entry"

# Multi-line append
append-file "README.md" with ---

## New Section

Added after the fact.
---

copy-file

Copies a file or folder to a new location. Parent directories are created automatically. If copying a folder that already exists at the destination, it is replaced.

copy-file "src/app.py" to "backup/app.py"
copy-file "src" to "src_backup"

move-file

Moves a file or folder to a new location. Parent directories are created automatically.

move-file "build/output.js" to "dist/app.js"
move-file "temp" to "archive/temp"

make-zip

Creates a zip archive from a file or folder. Folder structure is preserved inside the zip.

make-zip "releases/v1.0.zip" from "dist"
make-zip "releases/app.zip" from "dist/app.py"

set

Defines a variable. Variables are referenced anywhere using {{name}} syntax — in paths, content, template calls, and loop bodies.

set project "my-app"
set version "1.0.0"

make-file "VERSION" with "{{version}}"
make-file "src/main.py" with "# {{project}} v{{version}}"

load-vars

Loads variables from an .ebv (External Bytecraft Variables) file. Useful for sharing config across multiple scripts.

load-vars "config.ebv"

config.ebv:

# Project config
project = my-app
version = 1.0.0
author = Sourasish Das
env = prod

Lines starting with # are ignored. Values do not need quotes.


for

Loops over a list of values or an integer range. The loop variable is available inside the body via {{name}}. Loops can be nested.

# Value list
for name in "auth" "api" "db"
  make-folder "src/{{name}}"
  make-file "src/{{name}}/__init__.py" with "# {{name}} module"
end-for

# Integer range
for i in 1 to 5
  make-file "logs/day_{{i}}.log"
end-for

if

Conditionally executes a block. Supports file existence checks and variable comparisons. Can be nested inside loops and other if blocks.

# File existence
if exists "src/main.py"
  make-file "src/backup.py" with "# backup"
end-if

if not exists "dist"
  make-folder "dist"
end-if

# Variable comparison
if "{{env}}" is "prod"
  include "hardening.bc"
end-if

if "{{env}}" is not "dev"
  make-file "prod-only.txt" with "production config"
end-if

define-template / use-template

Templates let you define reusable scaffolding blocks and stamp them out with different values. Variables passed to use-template are local to that call and do not leak back into the outer script.

define-template "module"
  make-folder "src/{{name}}"
  make-file "src/{{name}}/__init__.py"
  make-file "src/{{name}}/main.py" with "# {{name}} module — {{project}}"
end-template

use-template "module" name "auth"
use-template "module" name "api"
use-template "module" name "db"

include

Runs another .bc file inline with fully shared state. Variables, templates, the working folder, and strict mode all carry across in both directions. Paths are resolved relative to the calling script's directory.

include "base.bc"
include "templates/python.bc"

strict on / strict off

In strict mode, warnings become fatal errors — undefined variables, unknown commands, and missing source files all halt execution immediately. Can be toggled on and off within the same script.

strict on

make-file "VERSION" with "{{version}}"   # fine if version is set
make-file "bad.txt" with "{{typo}}"      # ERROR: halts execution

strict off

Comments

Lines starting with # are ignored.

# This is a comment

Forgiving Syntax

Bytecraft is intentionally forgiving. Quotes are optional — if they're missing, Bytecraft will recover and interpret your intent:

make-file hello.txt with Hello World

is treated the same as:

make-file "hello.txt" with "Hello World"

Unknown commands print a warning and are skipped rather than crashing the script. Use strict on if you want the opposite behaviour.


Full Example

# Full project scaffold

strict on

load-vars "project.ebv"

set-working-folder "{{project}}"

# Stamp out feature modules
define-template "module"
  make-folder "src/{{name}}"
  make-file "src/{{name}}/__init__.py"
  make-file "src/{{name}}/main.py" with "# {{name}} — {{project}}"
end-template

for name in "auth" "api" "db" "admin"
  use-template "module" name "{{name}}"
end-for

# Generate per-environment configs
for env in "dev" "staging" "prod"
  if "{{env}}" is "prod"
    make-file "config/{{env}}.json" with "{ \"strict\": true }"
  end-if
  if "{{env}}" is not "prod"
    make-file "config/{{env}}.json" with "{ \"strict\": false }"
  end-if
end-for

# Static files
make-file "VERSION" with "{{version}}"

make-file "README.md" with ---
# {{project}}

Version: {{version}}
Author: {{author}}
---

# Build log
make-file "build.log" with "Build started"
append-file "build.log" with "Modules scaffolded"
append-file "build.log" with "Configs generated"

# Only package if we're in prod
if "{{env}}" is "prod"
  copy-file "src" to "dist/src"
  make-zip "releases/{{project}}-{{version}}.zip" from "dist"
  append-file "build.log" with "Release zipped"
end-if

project.ebv:

project = my-app
version = 1.0.0
author = Sourasish Das
env = prod

Limitations (v0.3.0)

  • No arithmetic or string operations in expressions
  • No else / else-if blocks
  • No nested variable references (e.g. {{{{key}}}})

Roadmap

  • Variables and interpolation
  • Multi-line file content blocks
  • copy-file and move-file
  • make-zip
  • append-file
  • Templates (define-template / use-template)
  • include
  • Strict mode
  • for loops (value lists and ranges)
  • if conditionals (exists checks and variable comparisons)
  • .ebv external variable files
  • else / else-if
  • Delete commands (delete-file, delete-folder)
  • Arithmetic in ranges and variables

License

Server-Lab Open-Control License (SOCL) 1.0
Copyright (c) 2025 Sourasish Das

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bytecraft-0.3.0.tar.gz (14.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

bytecraft-0.3.0-py3-none-any.whl (12.0 kB view details)

Uploaded Python 3

File details

Details for the file bytecraft-0.3.0.tar.gz.

File metadata

  • Download URL: bytecraft-0.3.0.tar.gz
  • Upload date:
  • Size: 14.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for bytecraft-0.3.0.tar.gz
Algorithm Hash digest
SHA256 c3a21c07f25b489e46fb803d3944c070d0a50727e614a09fcd09a3f8c0d645e4
MD5 7d5b0d69ed4f40643a52ec8d0242ffa0
BLAKE2b-256 a24414c014180f2b92a4a37e395a6585363571f67a1891500e2e7acefb069796

See more details on using hashes here.

File details

Details for the file bytecraft-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: bytecraft-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 12.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for bytecraft-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c718cf6c78998c79f0c2b12532db11e81d70fc3ca0d148bf27ae64463e002035
MD5 06e70d2cbaeeb72b07a73876f3a72764
BLAKE2b-256 d2c9bcc76e0daa4539a93d9156a09d5f3b0efdf0444c8c2c3072f07e674bda6f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page