{"id":45278318,"url":"https://github.com/bosley/truk","last_synced_at":"2026-02-21T02:04:24.053Z","repository":{"id":329056936,"uuid":"1111338446","full_name":"bosley/truk","owner":"bosley","description":"truk is a statically-typed systems programming language that compiles to C. It provides manual memory management with runtime bounds checking and a C-like syntax","archived":false,"fork":false,"pushed_at":"2025-12-19T00:57:13.000Z","size":806,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-20T17:15:04.130Z","etag":null,"topics":["c","compiler","compilers","language"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bosley.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-06T18:32:18.000Z","updated_at":"2025-12-18T06:57:09.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/bosley/truk","commit_stats":null,"previous_names":["bosley/truk"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/bosley/truk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bosley%2Ftruk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bosley%2Ftruk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bosley%2Ftruk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bosley%2Ftruk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bosley","download_url":"https://codeload.github.com/bosley/truk/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bosley%2Ftruk/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29671513,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-21T00:11:43.526Z","status":"online","status_checked_at":"2026-02-21T02:00:07.432Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c","compiler","compilers","language"],"created_at":"2026-02-21T02:04:20.917Z","updated_at":"2026-02-21T02:04:24.009Z","avatar_url":"https://github.com/bosley.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# truk\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"tools/syntax/icon.png\" alt=\"truk\" width=\"200\"/\u003e\n\u003c/p\u003e\n\ntruk is a statically-typed systems programming language that compiles to C. It provides manual memory management with runtime bounds checking, modern language features, and seamless C interoperability.\n\n## Quick Start\n\n```bash\ntruk run example.truk\ntruk compile example.truk -o program\ntruk test tests/\n```\n\nSee [docs/getting-started/building.md](docs/getting-started/building.md) for build instructions and [docs/start-here.md](docs/start-here.md) for complete documentation.\n\n## What Makes truk Different?\n\n- **Systems Programming with Safety:** Manual memory management with runtime bounds checking\n- **Modern Language Features:** Enums, pattern matching, lambdas, defer, tuples, and maps\n- **C Interoperability:** Seamless integration with C libraries and headers\n- **Fast Compilation:** Compiles to C using TCC backend with JIT execution mode\n- **No Garbage Collection:** Explicit memory management with no runtime overhead\n- **Built-in Testing:** Convention-based test framework with no external dependencies\n\n## Feature Showcase\n\n\u003cdetails\u003e\n\u003csummary\u003eEnums and Pattern Matching\u003c/summary\u003e\n\n```truk\nenum HttpStatus : i32 {\n    OK = 200,\n    NOT_FOUND = 404,\n    SERVER_ERROR = 500\n}\n\nfn handle_response(status: HttpStatus) : i32 {\n    match status {\n        case HttpStatus.OK =\u003e return 0,\n        case HttpStatus.NOT_FOUND =\u003e return 1,\n        case HttpStatus.SERVER_ERROR =\u003e return 2,\n        _ =\u003e return -1,\n    }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eMultiple Return Values and Destructuring\u003c/summary\u003e\n\n```truk\nfn divide(a: i32, b: i32) : (bool, i32) {\n    if b == 0 {\n        return false, 0;\n    }\n    return true, a / b;\n}\n\nfn main() : i32 {\n    let success, result = divide(10, 2);\n    if success {\n        return result;\n    }\n    return -1;\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eDefer for Automatic Cleanup\u003c/summary\u003e\n\n```truk\nfn process_file(filename: *u8) : i32 {\n    var file: *File = open_file(filename);\n    defer close_file(file);\n    \n    var buffer: []u8 = make(@u8, 1024);\n    defer delete(buffer);\n    \n    return 0;\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eMaps with Type-Safe Keys and Values\u003c/summary\u003e\n\n```truk\nfn count_words(text: []u8) : i32 {\n    var counts: map[*u8, i32] = make(@map[*u8, i32]);\n    defer delete(counts);\n    \n    counts[\"hello\"] = 5;\n    counts[\"world\"] = 3;\n    \n    var total: i32 = 0;\n    each(counts, \u0026total, fn(key: *u8, val: *i32, ctx: *i32) : bool {\n        *ctx = *ctx + *val;\n        return true;\n    });\n    \n    return total;\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eLambdas for Functional Programming\u003c/summary\u003e\n\n```truk\nfn map_array(arr: []i32, f: fn(i32) : i32) : void {\n    var i: u64 = 0;\n    var len: u64 = len(arr);\n    while i \u003c len {\n        arr[i] = f(arr[i]);\n        i = i + 1;\n    }\n}\n\nfn main() : i32 {\n    var arr: []i32 = make(@i32, 3);\n    defer delete(arr);\n    \n    arr[0] = 1;\n    arr[1] = 2;\n    arr[2] = 3;\n    \n    map_array(arr, fn(x: i32) : i32 {\n        return x * 2;\n    });\n    \n    return arr[0] + arr[1] + arr[2];\n}\n```\n\n\u003c/details\u003e\n\n## Language Features\n\n### Type System\n\n**Primitive types:**\n- Signed integers: `i8`, `i16`, `i32`, `i64`\n- Unsigned integers: `u8`, `u16`, `u32`, `u64`\n- Floating point: `f32`, `f64`\n- Boolean: `bool`\n- Character: `i8` (char literals: `'a'`, `'\\n'`, `'\\t'`, `'\\x41'`, `'\\0'`)\n- Void: `void`\n\n\u003cdetails\u003e\n\u003csummary\u003eCharacter literal examples\u003c/summary\u003e\n\n```truk\nfn classify_char(c: i8) : i32 {\n    match c {\n        case 'a' =\u003e return 1,\n        case 'b' =\u003e return 2,\n        case '\\n' =\u003e return 10,\n        case '\\t' =\u003e return 9,\n        case '\\0' =\u003e return 0,\n        case '\\x41' =\u003e return 65,\n        _ =\u003e return -1,\n    }\n}\n\nfn main() : i32 {\n    var letter: i8 = 'A';\n    var newline: i8 = '\\n';\n    var hex: i8 = '\\x48';\n    \n    return classify_char(letter);\n}\n```\n\nCharacter literals are `i8` type and support escape sequences: `\\n`, `\\t`, `\\r`, `\\0`, `\\\\`, `\\'`, `\\\"`, and hex codes `\\xHH`.\n\n\u003c/details\u003e\n\n**Arrays:**\n- Sized arrays: `[10]i32` (stack allocated)\n- Unsized arrays: `[]i32` (heap allocated slices)\n- Multi-dimensional: `[5][10]i32`\n\n**Maps:**\n- Hash tables with typed keys and values: `map[K, V]`\n- Key types: primitives (i8-i64, u8-u64, f32, f64, bool) or string pointers (*u8, *i8)\n- Indexing returns pointer: `m[\"key\"]` returns `*V` (nil if key doesn't exist)\n- Nil checking: `if m[\"key\"] != nil { ... }`\n\n**Pointers:**\n- Single: `*i32`\n- Multiple indirection: `**i32`\n\n**User-defined types:**\n- Structs with named fields\n- Enums with typed values\n\n**Tuples:**\n- Multiple return values: `(i32, i32)`\n- Destructuring with `let`: `let x, y = get_coords();`\n\n### Control Flow\n\n- `if`/`else if`/`else` statements\n- `while` loops\n- `for` loops with C-style syntax\n- `match` expressions for pattern matching\n- `break` and `continue`\n- `return` statements\n- `defer` for cleanup operations\n\n### Enums\n\nType-safe enumerations with explicit underlying types:\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to see enum examples\u003c/summary\u003e\n\n```truk\nenum Status : i32 {\n    OK = 0,\n    ERROR = 1,\n    PENDING = 2\n}\n\nenum Color : u8 {\n    RED = 0xFF0000,\n    GREEN = 0x00FF00,\n    BLUE = 0x0000FF\n}\n\nfn main() : i32 {\n    var status: Status = Status.OK;\n    var color: Color = Color.RED;\n    \n    if status == Status.OK {\n        return 0;\n    }\n    return 1;\n}\n```\n\nEnums can be cast to their underlying type and used in expressions, function parameters, struct fields, and more.\n\n\u003c/details\u003e\n\n### Match Expressions\n\nPattern matching for clean control flow:\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to see match examples\u003c/summary\u003e\n\n```truk\nenum Status : i32 { OK = 0, ERROR = 1, PENDING = 2 }\n\nfn handle_status(s: Status) : i32 {\n    match s {\n        case Status.OK =\u003e return 0,\n        case Status.ERROR =\u003e {\n            return 1;\n        },\n        case Status.PENDING =\u003e return 2,\n        _ =\u003e return -1,\n    }\n}\n\nfn classify_number(x: i32) : i32 {\n    match x {\n        case 0 =\u003e return 0,\n        case 1 =\u003e return 1,\n        case 42 =\u003e return 42,\n        _ =\u003e return -1,\n    }\n}\n\nfn main() : i32 {\n    var c: i8 = 'a';\n    match c {\n        case 'a' =\u003e return 1,\n        case 'b' =\u003e return 2,\n        _ =\u003e return 0,\n    }\n}\n```\n\nMatch expressions support integers, characters, booleans, enums, and pointers. The wildcard `_` case is required.\n\n\u003c/details\u003e\n\n### Memory Management\n\nManual memory management with explicit allocation and deallocation:\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to see memory management examples\u003c/summary\u003e\n\n```truk\nvar ptr: *i32 = make(@i32);\n*ptr = 42;\ndelete(ptr);\n\nvar count: u64 = 100;\nvar arr: []i32 = make(@i32, count);\narr[0] = 10;\ndelete(arr);\n\nvar m: map[*u8, i32] = make(@map[*u8, i32]);\nm[\"key\"] = 42;\ndelete(m);\n```\n\nRuntime bounds checking on all array accesses. Out-of-bounds access causes a panic.\n\n\u003c/details\u003e\n\n### Lambdas and Defer\n\nFirst-class functions and scope-based cleanup:\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to see lambda and defer examples\u003c/summary\u003e\n\n```truk\nfn process(x: i32, op: fn(i32) : i32) : i32 {\n    return op(x);\n}\n\nfn main() : i32 {\n    var result: i32 = process(10, fn(x: i32) : i32 {\n        return x * 2;\n    });\n    \n    var ptr: *i32 = make(@i32);\n    defer delete(ptr);\n    \n    *ptr = result;\n    return *ptr;\n}\n\nfn with_map() : i32 {\n    var m: map[*u8, i32] = make(@map[*u8, i32]);\n    defer delete(m);\n    \n    m[\"count\"] = 0;\n    \n    each(m, nil, fn(key: *u8, val: *i32, ctx: *void) : bool {\n        *val = *val + 1;\n        return true;\n    });\n    \n    var ptr: *i32 = m[\"count\"];\n    if ptr != nil {\n        return *ptr;\n    }\n    return 0;\n}\n```\n\nLambdas are non-capturing and compile to static functions. Defer executes cleanup code when exiting the current scope.\n\n\u003c/details\u003e\n\n### Builtin Functions\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to see builtin functions\u003c/summary\u003e\n\n**Memory Management:**\n- `make(@type)` - allocate single value on heap\n- `make(@type, count)` - allocate array on heap\n- `make(@map[K, V])` - allocate and initialize map\n- `delete(ptr)` - free allocated memory (single value, array, or map)\n- `delete(m[key])` - remove key-value pair from map\n\n**Array Operations:**\n- `len(arr)` - get array length\n\n**Type Information:**\n- `sizeof(@type)` - get type size in bytes\n\n**Iteration:**\n- `each(collection, context, callback)` - iterate over maps or slices\n\n**Error Handling:**\n- `panic(message: []u8)` - abort with error message\n\nType parameters use `@` prefix syntax to pass types to builtins.\n\n\u003c/details\u003e\n\n### Complete Example\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to see a complete program demonstrating key features\u003c/summary\u003e\n\n```truk\nenum Status : i32 {\n    SUCCESS = 0,\n    NOT_FOUND = 1,\n    ERROR = 2\n}\n\nstruct Point {\n    x: i32,\n    y: i32\n}\n\nfn distance_squared(p1: Point, p2: Point) : i32 {\n    var dx: i32 = p2.x - p1.x;\n    var dy: i32 = p2.y - p1.y;\n    return dx * dx + dy * dy;\n}\n\nfn find_point(points: []Point, target_x: i32) : (Status, Point) {\n    var i: u64 = 0;\n    var len: u64 = len(points);\n    \n    while i \u003c len {\n        if points[i].x == target_x {\n            return Status.SUCCESS, points[i];\n        }\n        i = i + 1;\n    }\n    \n    return Status.NOT_FOUND, Point{x: 0, y: 0};\n}\n\nfn main() : i32 {\n    var count: u64 = 3;\n    var points: []Point = make(@Point, count);\n    defer delete(points);\n    \n    points[0] = Point{x: 0, y: 0};\n    points[1] = Point{x: 3, y: 4};\n    points[2] = Point{x: 6, y: 8};\n    \n    var cache: map[*u8, i32] = make(@map[*u8, i32]);\n    defer delete(cache);\n    \n    cache[\"first\"] = distance_squared(points[0], points[1]);\n    cache[\"second\"] = distance_squared(points[1], points[2]);\n    \n    let status, point = find_point(points, 3);\n    \n    match status {\n        case Status.SUCCESS =\u003e {\n            var ptr: *i32 = cache[\"first\"];\n            if ptr != nil {\n                return *ptr;\n            }\n            return 0;\n        },\n        case Status.NOT_FOUND =\u003e return 1,\n        _ =\u003e return 2,\n    }\n}\n```\n\nThis example demonstrates:\n- Enum definitions and usage\n- Struct definitions\n- Array allocation with `make`\n- Defer for automatic cleanup\n- Map creation and indexing\n- Multiple return values with tuples\n- Let destructuring\n- Match expressions\n- Proper memory management\n\n\u003c/details\u003e\n\n### C Interoperability\n\ntruk provides seamless interoperability with C through `cimport` and `extern` declarations.\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to see C interop examples\u003c/summary\u003e\n\n**Importing C headers:**\n```truk\ncimport \u003cstdio.h\u003e;\ncimport \u003cmath.h\u003e;\ncimport \"myheader.h\";\n```\n\n**Declaring C functions:**\n```truk\nextern fn printf(fmt: *i8, ...args): i32;\nextern fn sqrt(x: f64): f64;\nextern fn fopen(filename: *i8, mode: *i8): *FILE;\n```\n\n**Opaque structs (forward declarations):**\n```truk\nextern struct FILE;\n\nextern fn fopen(filename: *i8, mode: *i8): *FILE;\nextern fn fclose(file: *FILE): i32;\n```\n\n**Defined structs (with layout):**\n```truk\ncimport \u003ctime.h\u003e;\n\nextern struct tm {\n    tm_sec: i32,\n    tm_min: i32,\n    tm_hour: i32,\n    tm_mday: i32,\n    tm_mon: i32,\n    tm_year: i32\n}\n\nextern fn time(timer: *i64): i64;\nextern fn localtime(timer: *i64): *tm;\n```\n\n**C variables:**\n```truk\ncimport \u003cerrno.h\u003e;\n\nextern var errno: i32;\nextern var stdin: *FILE;\n```\n\n**Complete example:**\n```truk\ncimport \u003cstdio.h\u003e;\ncimport \u003cmath.h\u003e;\n\nextern struct FILE;\nextern fn fopen(filename: *i8, mode: *i8): *FILE;\nextern fn fclose(file: *FILE): i32;\nextern fn fprintf(file: *FILE, fmt: *i8, ...args): i32;\nextern fn sqrt(x: f64): f64;\n\nfn main(): i32 {\n    var result: f64 = sqrt(16.0);\n    \n    var f: *FILE = fopen(\"output.txt\", \"w\");\n    if f != nil {\n        fprintf(f, \"sqrt(16) = %f\\n\", result);\n        fclose(f);\n    }\n    \n    return 0;\n}\n```\n\nSee `docs/language/imports.md` for complete details on C interop.\n\n\u003c/details\u003e\n\n### Privacy System\n\nConvention-based privacy with file and shard scoping:\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to see privacy examples\u003c/summary\u003e\n\n```truk\nstruct Connection {\n    host: *u8,\n    port: u16,\n    _socket_fd: i32,\n    _is_connected: bool\n}\n\nfn _internal_helper(x: i32) : i32 {\n    return x * 2;\n}\n\nfn public_api(x: i32) : i32 {\n    return _internal_helper(x);\n}\n```\n\nIdentifiers starting with `_` are private to their file. Files can declare shards to share private members:\n\n```truk\nshard \"database_internal\";\n\nfn _shared_internal() : void {\n}\n```\n\nSee [docs/language/privacy.md](docs/language/privacy.md) for details.\n\n\u003c/details\u003e\n\n### Testing\n\nBuilt-in testing framework with convention-based test discovery:\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to see testing examples\u003c/summary\u003e\n\n```truk\nextern struct __truk_test_context_s;\nextern fn __truk_test_assert_i32(t: *__truk_test_context_s, \n                                 expected: i32, actual: i32, \n                                 msg: *u8) : void;\n\nfn add(a: i32, b: i32) : i32 {\n    return a + b;\n}\n\nfn test_addition(t: *__truk_test_context_s) : void {\n    __truk_test_assert_i32(t, 4, add(2, 2), \"2+2 should equal 4\");\n    __truk_test_assert_i32(t, 10, add(7, 3), \"7+3 should equal 10\");\n}\n\nfn test_setup(t: *__truk_test_context_s) : void {\n}\n\nfn test_teardown(t: *__truk_test_context_s) : void {\n}\n```\n\nRun tests with:\n```bash\ntruk test math.truk\ntruk test tests/\n```\n\nSee [docs/language/testing.md](docs/language/testing.md) for the complete testing API.\n\n\u003c/details\u003e\n\n## Compilation\n\ntruk compiles to C and uses TCC (Tiny C Compiler) internally as the backend. The compiler performs type checking and validation before emitting C code.\n\n**Compilation modes:**\n- `truk run` - JIT compile and execute\n- `truk compile` - Compile to executable\n- `truk toc` - Transpile to C source files\n- `truk test` - Run tests\n\n## Documentation\n\n**[📚 Start Here - Complete Documentation Guide](docs/start-here.md)**\n\nThe documentation is organized into three sections:\n\n### Getting Started\n- [Building truk Programs](docs/getting-started/building.md) - Compilation commands and workflows\n\n### Language Reference\n- [Grammar](docs/language/grammar.md) - Complete language syntax\n- [Builtin Functions](docs/language/builtins.md) - Memory management, arrays, type operations\n- [Maps](docs/language/maps.md) - Hash table types and operations\n- [Defer Statements](docs/language/defer.md) - Scope-based cleanup\n- [Imports](docs/language/imports.md) - Module system and C interoperability\n- [Lambdas](docs/language/lambdas.md) - First-class functions and callbacks\n- [Privacy](docs/language/privacy.md) - File and shard-based privacy system\n- [Testing](docs/language/testing.md) - Built-in test framework\n- [Runtime Architecture](docs/language/runtime.md) - How truk programs execute\n\n### Compiler Internals\n- [Error Handling](docs/compiler-internals/error-handling.md) - Unified error reporting system\n- [Error Flow Diagrams](docs/compiler-internals/error-flow-diagram.md) - Error flow through compilation stages\n- [C Emitter](docs/compiler-internals/emitter.md) - Code generation architecture\n- [Type Checker](docs/compiler-internals/typechecker.md) - Type validation and semantic analysis\n\nVisit [docs/start-here.md](docs/start-here.md) for the full documentation index with navigation and examples.\n\n## Key Language Features at a Glance\n\n| Feature | Description | Example |\n|---------|-------------|---------|\n| **Enums** | Type-safe enumerations with explicit types | `enum Status : i32 { OK = 0 }` |\n| **Match** | Pattern matching for control flow | `match x { case 0 =\u003e ..., _ =\u003e ... }` |\n| **Tuples** | Multiple return values | `fn f() : (i32, i32) { return 1, 2; }` |\n| **Let** | Tuple destructuring | `let x, y = get_coords();` |\n| **Defer** | Scope-based cleanup | `defer delete(ptr);` |\n| **Lambdas** | First-class functions | `fn(x: i32) : i32 { return x * 2; }` |\n| **Maps** | Built-in hash tables | `map[*u8, i32]` |\n| **Each** | Iterator for maps and slices | `each(m, ctx, callback)` |\n| **Char Literals** | Character constants with escapes | `'a'`, `'\\n'`, `'\\x41'` |\n| **Privacy** | Convention-based with `_` prefix | `_private_field`, `_private_fn()` |\n| **Shards** | Shared privacy boundaries | `shard \"internal\";` |\n| **Testing** | Built-in test framework | `fn test_foo(t: *__truk_test_context_s)` |\n| **C Interop** | Seamless C integration | `cimport \u003cstdio.h\u003e; extern fn printf(...)` |\n\n## Memory Model\n\nStack allocation for local variables with sized arrays and structs. Heap allocation through explicit `make` calls. No garbage collection. Memory must be manually freed with `delete`. Double-free and use-after-free result in undefined behavior.\n\n## Contributing\n\ntruk is actively developed. See the [compiler internals documentation](docs/compiler-internals/) to understand the implementation, and check [todo.md](todo.md) for planned features and improvements.\n\n## License\n\nMIT","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbosley%2Ftruk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbosley%2Ftruk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbosley%2Ftruk/lists"}