newc TheHomelessTwig
winget install --id=TheHomelessTwig.newc -e GUI-driven C project scaffolding and management tool
winget install --id=TheHomelessTwig.newc -e GUI-driven C project scaffolding and management tool
A Rust GUI application for scaffolding, building, and managing C projects. Built on iced 0.14 with a multi-window MVU architecture.
src/, include/, build/, Makefile or CMakeLists.txt) with one command or via the GUI.c/.h pairs; auto-sync prototypes between source and headerLICENSE and stamps SPDX-License-Identifier into every generated source file. newc add reuses the project's chosen license for new modules.all, run, debug, release, strict, test, valgrind, valgrind-xml, analyse, cppcheck, coverage, or clean targets from the GUI, via make or cmake depending on how the project was scaffoldedrun target from a text field in the build panel.newc_builds.jsoncoverage buildanalyse, surfaced in the same diagnostics panelcompile_commands.json export — for clangd/clang-tidy/IDE integration outside newcmain(); unreachable functions highlightedL001 — gets() usageL002 — strcpy() without boundsL003 — scanf("%s") without width limitL004 — printf() with non-literal format stringL005 — assignment in conditionL006 — sprintf() without boundsL007 — malloc/calloc result not checked for NULLL008 — magic number literalsL009 — fopen() with no matching fclose()L010 — .h file missing #ifndef header guardL011 — free(ptr) not followed by ptr = NULLL012 — strlen() called in loop conditionL013 — atoi()/atof() usageL014 — returning address of local variableL015 — comparing pointer to non-zero integerL016 — strtok() not re-entrant (use strtok_r)L017 — = realloc(...) loses pointer on NULL return.c and .h files; preview then apply a replacement project-wide; click result to navigate to module at lineinput, math, display, array, algorithms, strings, linked_list, files, test_utils.c — extract functions from any existing source file~/.config/newc/functions/ as TOML filesA visual block-based builder for src/main.c:
src/main.c47 built-in C patterns across 11 categories. Available as a panel or detached OS window (⊞ button in header):
| Category | Examples |
|---|---|
| Loops | for, while, do-while |
| Conditionals | if/else chain, switch/case |
| Structs & Enums | struct definition, enum, typedef |
| Memory | malloc/free, realloc, calloc |
| Files | fopen/fclose, fgets loop, binary fread/fwrite |
| Pointers | pointer arithmetic, double pointer, function pointer |
| Strings | safe copy, string scan, string comparison |
| Recursion | factorial, fibonacci |
| Error Handling | errno/perror, NULL guard, exit on error |
| Preprocessor | include guard, macro with args, conditional compile |
| Misc | argc/argv main, qsort, memset |
11 built-in project templates: Calculator, Array Processor, Grade Manager, Menu-Driven App, File Parser, Linked List, Student Records, Recursion, CLI Arguments, State Machine, Unit Test Runner. Create custom templates by saving any project's structure.
Searchable reference for ~70 C standard library functions across stdio.h, stdlib.h, string.h, math.h, and time.h. Can be detached into a pop-out OS window (⊞ button in header). Jump directly to any function via Ctrl+P quick search.
Format any function using clang-format. Configurable style (file, LLVM, Google, Chromium, GNU, Microsoft) in Settings.
Override editor, terminal, and clang-format style on a per-project basis via .newc_config.toml in the project root. Editable from the Settings screen when a project is open. Also stores named build profiles (extra CFLAGS combos, selectable in the build panel).
test_utils at scaffold time (TEST_ASSERT_* / RUN_TEST macros)__A.zip| Document | Description |
|---|---|
| Architecture | System design, module map, key types, event loop, data flow |
| Data Formats | All TOML/JSON schemas with annotated examples |
| Building | Platform-specific build instructions (Linux, macOS, Windows, WSL2) |
| Contributing | Dev setup, adding features, lint rules, templates, commit style |
Download from GitHub Releases:
| Platform | File |
|---|---|
| Linux x86_64 | newc-x86_64-linux |
| Linux aarch64 | newc-aarch64-linux |
| macOS Apple Silicon | newc-aarch64-macos |
| Windows x86_64 | newc-x86_64-windows.exe |
# Linux x86_64
curl -fsSL https://github.com/TheHomelessTwig/newc-rs/releases/latest/download/newc-x86_64-linux \
-o /tmp/newc && chmod +x /tmp/newc && sudo mv /tmp/newc /usr/local/bin/newc
# Windows — installs to Program Files, adds to PATH, creates a Start Menu shortcut
irm https://raw.githubusercontent.com/TheHomelessTwig/newc-rs/main/packaging/install.ps1 | iex
# Windows — via winget (pending review: microsoft/winget-pkgs#391124)
winget install TheHomelessTwig.newc
| Manager | Command |
|---|---|
| Homebrew CLI (macOS/Linux) | brew tap thehomelesstwig/newc && brew install newc — builds from source via cargo |
| Homebrew GUI app (macOS, Apple Silicon) | brew install --cask thehomelesstwig/newc/newc — prebuilt .app, no Rust needed |
| AUR (Arch Linux) | yay -S newc-bin (or any AUR helper) |
| apt repo (Debian/Ubuntu, amd64) | see below — apt install newc after a one-time setup |
| winget (Windows) | winget install TheHomelessTwig.newc (pending review) |
The .deb, apt repo, and AUR packages all bundle the desktop launcher entry + icon alongside the binary, same as the install scripts below.
Self-hosted (not in the official Debian/Ubuntu archives) — one-time setup, then apt update/apt upgrade picks up new releases like any other repo:
curl -fsSL https://thehomelesstwig.github.io/newc-rs/apt/pubkey.asc | sudo gpg --dearmor -o /etc/apt/keyrings/newc.gpg
echo "deb [signed-by=/etc/apt/keyrings/newc.gpg] https://thehomelesstwig.github.io/newc-rs/apt stable main" | sudo tee /etc/apt/sources.list.d/newc.list
sudo apt update
sudo apt install newc
Notes:
packaging/aur/) is binary-based (-bin suffix per AUR convention) — installs the released binary directly, no Rust toolchain needed..deb from Releases still works too (sudo apt install ./newc_*_amd64.deb) if you'd rather not add a repo.winget install works for everyone.install.sh (this repo), the dotfiles installer, and packaging/install.ps1 all register newc with the OS app launcher in addition to installing the CLI binary:
~/.local/share/applications/newc.desktop + a hicolor SVG icon, so newc shows up in any XDG-compliant launcher (rofi, wofi, GNOME/KDE menus, …). Also bundled automatically in the .deb and AUR packages./Applications/newc.app bundle (for personal-use Launchpad/Spotlight access). brew install --cask thehomelesstwig/newc/newc installs exactly this (prebuilt, Apple Silicon only); the CLI Formula (brew install newc) no longer bundles it — install both if you want the launcher and a CLI built from source.install.ps1.On all three, newc (no args) opens the GUI directly — the CLI remains available from any shell since the binary still lives on PATH (/usr/local/bin, Homebrew's bin dir, or %ProgramFiles%\newc on Windows).
Requires Rust stable (via rustup), gcc/clang, and make (or cmake if scaffolding CMake projects).
git clone https://github.com/TheHomelessTwig/newc-rs.git
cd newc-rs
cargo build --release
sudo cp target/release/newc /usr/local/bin/newc
See docs/building.md for platform-specific instructions including WSL2.
newc # open GUI (terminal freed immediately)
newc gui # explicit form
newc gui ~/projects/myapp # open directly to a project
newc spawns itself with a hidden internal-gui flag as a detached child, freeing the terminal immediately. On Windows, CREATE_NO_WINDOW prevents a console window appearing alongside the GUI.
newc new # scaffold a new project (Makefile by default)
newc new --git # scaffold + git init
newc new --template calculator # scaffold from template
newc new --build-system cmake # scaffold with CMakeLists.txt instead of Makefile
newc new --license MIT # write LICENSE + stamp SPDX headers (MIT, Apache-2.0, GPL-2.0-only, GPL-3.0-only, BSD-3-Clause, Unlicense)
newc add # add a new module (.c + .h)
newc remove # interactively remove a module
newc remove --yes # remove by name, no prompt (scriptable)
newc list # list all modules
newc sync [module] # regenerate .h prototypes from .c definitions
newc check # list functions unreachable from main()
newc tidy # remove unreachable functions (with confirmation)
newc tidy --dry-run # show what tidy would remove, change nothing
newc tidy --yes # skip the confirmation prompt
newc stats # print function count and LOC per module
newc funcs [module] # list function signatures
newc search # search all .c and .h files (regex, case-insensitive)
newc lint [module] # run the L001–L017 linter; exits non-zero on findings (CI-friendly)
newc doc [function] # insert Doxygen stub comments above undocumented functions
newc build [target] # run a build target (default: all) — works for Makefile or CMakeLists.txt
newc test # alias for `newc build test`
list, stats, funcs, check, search, and lint accept --json for machine-readable output:
newc stats --json | jq '.total_loc'
newc check --json | jq '.[].name'
newc build targets: all, run, debug, release, strict, valgrind, valgrind-xml, analyse, cppcheck, coverage, test, clean, help. Auto-detects Makefile vs CMakeLists.txt and runs the equivalent make or cmake invocation with the same flags either way — debug/release/strict/coverage drive CMAKE_BUILD_TYPE/STRICT/COVERAGE for CMake projects, reconfiguring as needed (via CMakePresets.json if present).
All CLI commands except new and gui need to run inside a project (directory containing src/, include/, and a Makefile or CMakeLists.txt) — any subdirectory works; newc walks up to find the project root, like git. Build system is auto-detected from which file is present. A man page ships with the .deb package (man newc).
myapp/
├── src/
│ ├── main.c
│ ├── input.c
│ └── math.c
├── include/
│ ├── input.h
│ └── math.h
├── build/
├── Makefile # or CMakeLists.txt, depending on --build-system
├── .newc_meta.toml # course, assignment, due date, marks
├── .newc_builds.json # build history (last 100 records)
├── .gitignore # generated if --git flag used
└── LICENSE # generated if --license flag used
Config file: ~/.config/newc/config.toml
terminal = "foot" # terminal emulator for "Open in Editor"
editor = "nvim" # text editor
clang_format_style = "file" # clang-format style
scan_dirs = ["~/projects"] # directories scanned for projects on startup
[[workspaces]]
name = "CS101"
paths = ["/home/user/projects/assignment1", "/home/user/projects/assignment2"]
Custom functions in ~/.config/newc/functions/.toml:
module = "utils"
[[functions]]
name = "clamp"
description = "Clamp a value between min and max"
signature = "int clamp(int value, int min, int max)"
header_code = "int clamp(int value, int min, int max);"
impl_code = """
int clamp(int value, int min, int max) {
if (value < min) return min;
if (value > max) return max;
return value;
}"""
tags = ["math", "utility"]
requires = []
| Shortcut | Action |
|---|---|
Ctrl+P | Quick search (projects and functions) |
Ctrl+B | Build (all target) |
Ctrl+R | Refresh current project |
Ctrl+Z | Undo (Composer) |
Ctrl+Y / Ctrl+Shift+Z | Redo (Composer) |
Ctrl+S | Save (notes, module editor, header editor, build file editor) |
? | Open keyboard shortcuts panel |
Esc | Close topmost overlay (quick search, shortcuts, error) |
↑ ↓ | Navigate quick-search results |
Enter | Confirm quick-search selection |
Cargo workspace with two crates:
newc-rs/
├── newc-core/ # pure logic, no UI dependencies
└── newc/ # GUI + CLI binary (iced 0.14)
See docs/architecture.md for the full module map and design decisions.
| Crate | Purpose |
|---|---|
iced 0.14 | Retained-mode GUI (MVU, multi-window via daemon) |
clap | CLI argument parsing |
serde + toml + serde_json | Configuration and data serialisation |
rfd | Native file dialogs |
dirs | XDG config directory resolution |
chrono | Timestamps in build history |
notify | File system watcher |
tokio | Async runtime for iced subscriptions |
futures | Stream bridging for file watcher subscription |
anyhow | Error handling |
zip | Project export / assignment submission packer |
Self-update shells out to the system curl rather than linking an HTTP client (avoids a TLS dependency chain for two infrequent GET requests). Optional external tools, used if present on PATH: valgrind, cppcheck, gcov, clangd (hover).
MIT
/** @brief/@param/@return */ block above a function in both .c and .h; parsed comments render as formatted docs in the detail panelgets→fgets, strcpy→strncpy, sprintf→snprintf)clangd on PATH)