Skip to content

Commit a9feeaf

Browse files
committed
Update README and installer for BasaltOS 0.1.0 release
1 parent da14d52 commit a9feeaf

4 files changed

Lines changed: 525 additions & 115 deletions

File tree

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
name: Update install manifest
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths:
8+
- "os/**"
9+
- ".github/workflows/update-install-manifest.yml"
10+
workflow_dispatch:
11+
12+
permissions:
13+
contents: write
14+
15+
concurrency:
16+
group: update-install-manifest
17+
cancel-in-progress: true
18+
19+
jobs:
20+
update:
21+
name: Generate install-manifest.txt
22+
runs-on: ubuntu-latest
23+
24+
steps:
25+
- name: Check out repository
26+
uses: actions/checkout@v4
27+
with:
28+
fetch-depth: 0
29+
30+
- name: Generate manifest
31+
shell: python
32+
run: |
33+
from pathlib import Path
34+
import re
35+
36+
root = Path("os")
37+
output = Path("install-manifest.txt")
38+
allowed_path = re.compile(r"^os/[A-Za-z0-9._/-]+$")
39+
40+
if not root.is_dir():
41+
raise SystemExit("The os directory does not exist.")
42+
43+
def is_runtime_path(path: str) -> bool:
44+
return (
45+
path == "os/system/config.dat"
46+
or path.startswith("os/system/logs/")
47+
or path.startswith("os/users/")
48+
)
49+
50+
entries = []
51+
for file in sorted(path for path in root.rglob("*") if path.is_file()):
52+
relative = file.as_posix()
53+
if is_runtime_path(relative):
54+
continue
55+
if not allowed_path.fullmatch(relative):
56+
raise SystemExit(f"Unsupported installer path: {relative}")
57+
if any(part in {".", ".."} for part in file.parts):
58+
raise SystemExit(f"Unsafe installer path: {relative}")
59+
entries.append(f"{relative}|{file.stat().st_size}")
60+
61+
if not entries:
62+
raise SystemExit("No installable BasaltOS files were found.")
63+
64+
content = "\n".join([
65+
"# BasaltOS installation manifest v1",
66+
"# Format: repository path|size in bytes",
67+
"# Generated by .github/workflows/update-install-manifest.yml",
68+
"# Runtime state such as users, logs, and system/config.dat is intentionally excluded.",
69+
*entries,
70+
"",
71+
])
72+
output.write_text(content, encoding="utf-8", newline="\n")
73+
print(f"Generated {len(entries)} entries in {output}.")
74+
75+
- name: Commit updated manifest
76+
shell: bash
77+
run: |
78+
if [ -z "$(git status --porcelain -- install-manifest.txt)" ]; then
79+
echo "install-manifest.txt is already up to date."
80+
exit 0
81+
fi
82+
83+
git config user.name "github-actions[bot]"
84+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
85+
git add install-manifest.txt
86+
git commit -m "chore: update install manifest"
87+
git push

README.md

Lines changed: 139 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,141 @@
11
# BasaltOS
22

3-
A lightweight, public operating system for ComputerCraft, inspired by Basalt.
4-
5-
Overview
6-
- BasaltOS is a modular, minimal OS built on Basalt UI components. It's intended as a starting point for building and testing apps and UI features in a ComputerCraft environment.
7-
8-
Key Features
9-
- App launcher and startup script (`startup.lua`)
10-
- Organized system layout under `system/` and `apps/`
11-
- Basalt UI library inside `lib/public/basalt/` for rapid UI development
12-
- Logging and service modules in `logs/` and `services/`
13-
- Shared binary [FLIMG v1](system/lib/public/FLIMG.md) images with RGB palettes,
14-
2x3 subpixels, layers, animation timing, RAW/RLE blocks and frame deltas
15-
- FLIMG Studio under `system/apps/flimgstudio` for lossless pixel/cell editing,
16-
palettes, layers, timelines and BIMG/OSF import
17-
18-
Developing
19-
- Apps: Create a new folder in `apps/` with an `app.json` and `main.lua` to register an app.
20-
- Plugins/Themes: Extend or modify items in `lib/public/basalt/plugins/`.
21-
- Debugging: Check `logs/` for runtime messages and `services/` for service status.
22-
23-
Basalt render pacing
24-
- `basalt.setRenderInterval(seconds)` limits automatic render passes while
25-
continuing to process every input event. Rapid invalidations are coalesced
26-
and a trailing timer guarantees that the newest state is rendered.
27-
- `basalt.getRenderInterval()` returns the configured interval.
28-
- `basalt.flush()` immediately renders pending changes. An interval of `0`
29-
restores render-after-every-event behavior.
30-
- BasaltOS uses an interval of `0.05` seconds (at most 20 automatic renders
31-
per second).
32-
33-
Filely file icons
34-
- An app associated with a file type may declare a colored 1x1 icon in `app.json`:
35-
`"file_icon": {"char": 131, "fg": "white", "bg": "lightBlue"}`.
36-
- `char` is a ComputerCraft character code from 0 to 255; `fg` and `bg` are optional `colors.*` names or values.
37-
- A missing `fg` or `bg` uses Filely's current row background. The legacy `color` field is accepted as an alias for `bg`.
38-
- Filely renders the glyph as a subpixel icon. Files without a declared icon use character 131 in light gray; folders use character 131 in yellow.
39-
40-
System-wide file operations
41-
- Apps can access the `fileops` service through `require("app").fileops`.
42-
- `fileops.copy(path)` and `fileops.cut(path)` place a typed file selection on the shared clipboard.
43-
- `fileops.paste(directory)` copies or moves it, choosing a friendly unique name when the target already exists.
44-
- `fileops.canPaste(directory)` and `fileops.getClipboardInfo()` allow UIs to present the same actions as Filely and the desktop.
45-
46-
Basalt Store
47-
- The versioned [Basalt Store catalog format](BASALT_STORE_CATALOG.md) lists every app and its explicit GitHub-hosted files without using the GitHub API.
48-
- The `basaltstore` service validates and caches the catalog per user, retaining the last good catalog for offline use.
49-
- Store installs are staged, matched against the catalog ID/version, and handed to the Registry only after every declared file is present.
50-
51-
Window close requests
52-
- Managed apps can register `window.setCloseHandler(function(resolve) ... end)`.
53-
- Call `resolve(true)` to allow the close or `resolve(false)` to cancel it. The callback may answer later, so confirmation dialogs can be asynchronous.
54-
- `window.setCloseHandler(nil)` removes the handler. While a request is pending, repeated close clicks are coalesced.
55-
- Process termination, including Task Manager's `End task`, forcibly closes the window and bypasses the handler.
56-
57-
Contributing
58-
- Contributions are welcome. Open issues or PRs with a brief description and reproduction steps or screenshots when applicable.
59-
60-
License
61-
- See `LICENSE` for license details.
62-
63-
Contact
64-
- For questions or feedback, open an issue or contact the maintainer via the repository.
65-
66-
Enjoy building with BasaltOS!
3+
BasaltOS is a desktop operating system for
4+
[CC:Tweaked](https://tweaked.cc/) built with
5+
[Basalt 2.5](https://github.com/Pyroxenium/Basalt2/tree/basalt2.5).
6+
It combines a familiar windowed desktop with a modular service and app
7+
architecture designed specifically for ComputerCraft.
8+
9+
> BasaltOS is currently an early preview (`0.1.0`).
10+
11+
## Highlights
12+
13+
- Window manager with movable, resizable and focus-aware application windows
14+
- Desktop, taskbar, start menu, launcher and system notifications
15+
- Local user accounts with separate home directories and settings
16+
- Shared clipboard, drag and drop, file operations and file associations
17+
- Basalt Store for discovering and installing additional applications
18+
- Device Manager for inspecting attached ComputerCraft peripherals
19+
- Built-in support for Basalt 2.5, Obsidian and FLIMG-based images
20+
- Service-oriented internals with isolated application environments
21+
22+
## Included applications
23+
24+
BasaltOS ships with a practical starter set:
25+
26+
- **Filely** — file manager with copy, cut, paste and app associations
27+
- **Terminal** and **Shell** — graphical and native command-line access
28+
- **Notepad** and **Editor** — text editing and source-code workflows
29+
- **Calculator** and **Calendar** — compact offline utilities
30+
- **Settings** — appearance and system configuration
31+
- **Task Manager** — inspect, focus, pause and terminate processes
32+
- **Device Manager** — inspect connected peripherals
33+
- **Basalt Store** — browse and install BasaltOS applications
34+
- **Paint**, **Image Viewer** and **Pastebin** integrations
35+
36+
## Requirements
37+
38+
- An Advanced Computer running a current version of CC:Tweaked
39+
- A terminal resolution of at least `51x19`
40+
- The HTTP API enabled
41+
- Approximately 1.5 MB of installed storage
42+
- Approximately 1.5 MB of additional free space while installing or updating
43+
44+
The default ComputerCraft computer storage limit may be too small. If the
45+
installer reports insufficient space, increase the computer space limit in
46+
your CC:Tweaked or CraftOS-PC configuration before continuing.
47+
48+
## Installation
49+
50+
Run this command from the CraftOS shell:
51+
52+
```shell
53+
wget run https://raw.githubusercontent.com/Pyroxenium/BasaltOS/refs/heads/main/install.lua
54+
```
55+
56+
The installer downloads the current release, stages it before making changes,
57+
and installs BasaltOS into the computer root. It preserves:
58+
59+
- Existing local users and their files under `/users`
60+
- Machine configuration in `/system/config.dat`
61+
- Runtime logs under `/system/logs`
62+
- The previous `startup.lua`, saved as `startup.before-basaltos.lua`
63+
64+
If applying the installation fails, files already changed during that attempt
65+
are restored automatically. After installation, select **Reboot** to enter
66+
BasaltOS.
67+
68+
On the first boot, BasaltOS asks you to create the first local administrator.
69+
There is no default username or password.
70+
71+
### Updating
72+
73+
Run the same installation command again. The installer replaces system files
74+
while retaining local accounts, user data and configuration.
75+
76+
## Developing applications
77+
78+
Applications live in `/system/apps/<app-id>/` and normally contain:
79+
80+
```text
81+
myapp/
82+
├── app.json
83+
├── main.lua
84+
├── icon.bimg
85+
└── taskbar.bimg
86+
```
87+
88+
A minimal `app.json` looks like this:
89+
90+
```json
91+
{
92+
"id": "myapp",
93+
"name": "My App",
94+
"version": "1.0.0",
95+
"description": "A BasaltOS application",
96+
"author": "Your Name",
97+
"category": "utilities",
98+
"executable": "main.lua",
99+
"singleton": false,
100+
"window": {
101+
"fullscreen": false,
102+
"resizable": true,
103+
"default_width": 32,
104+
"default_height": 12,
105+
"min_width": 20,
106+
"min_height": 8
107+
}
108+
}
109+
```
110+
111+
Inside an app, `require("app")` exposes the public BasaltOS services. Basalt,
112+
Obsidian and FLIMG are available from the public library directory.
113+
114+
The most relevant project directories are:
115+
116+
```text
117+
os/
118+
├── startup.lua
119+
└── system/
120+
├── apps/ Built-in applications
121+
├── assets/ Shared icons and visual assets
122+
├── core/ Kernel and core APIs
123+
├── lib/public/ Public application libraries
124+
└── services/ Desktop and operating-system services
125+
```
126+
127+
The installer reads `install-manifest.txt`. A GitHub Actions workflow
128+
regenerates and commits it automatically whenever files under `os/` change.
129+
Runtime state (`users`, logs and `system/config.dat`) is intentionally excluded.
130+
131+
## Contributing
132+
133+
Bug reports and pull requests are welcome. Please include clear reproduction
134+
steps and screenshots for visual issues where possible:
135+
136+
- [Report an issue](https://github.com/Pyroxenium/BasaltOS/issues)
137+
- [Open a pull request](https://github.com/Pyroxenium/BasaltOS/pulls)
138+
139+
## License
140+
141+
BasaltOS is released under the [MIT License](LICENSE).

0 commit comments

Comments
 (0)