Compare commits

..
43 Commits
Author SHA1 Message Date
me 8d01548627 backups, no longer include the SFTP directory. 2026-11-07 20:12:51 -07:00
me f587ca1e5e tunnel, keep the loop in the foreground so that the output makes it to the log. 2026-11-06 14:53:16 -07:00
me bbffe8c69a tunnel, add green light output for loop. 2026-11-04 19:50:58 -07:00
me 768cabfe45 tunnel, add task which makes sure the main directory is 755 so that users may view the files. 2026-11-04 19:20:13 -07:00
me b1bdc953c2 tunnel, restart the service if the remote host no longer forwards to the local process. 2026-11-04 19:11:51 -07:00
me 1764ca510f test, remove java and docker as they've become stable. 2026-11-04 08:50:34 -07:00
me 7f986e51d3 AGENTS.md, add coding conventions and layout logistics including code snippets and example programs. 2026-11-04 08:48:26 -07:00
me d0970f5971 i3, increase startup volume to 75 from 25. 2026-11-03 13:56:11 -07:00
me d94397349b ai, begin refactoring sections into their own plays, starting with Sandbox and its AGENTS.md file. 2026-11-03 13:36:23 -07:00
me bb1514c33d llm, AGENTS.md, cover downgrades not being preferred. 2026-11-03 13:20:48 -07:00
me 0581ea62df docker, fix network sync run file permissions. 2026-11-03 08:45:50 -07:00
me 0332289742 llm, move enabling docker to docker playbook. 2026-11-02 20:51:42 -07:00
me a3a647318d docker, ensure container networks accurately reflect host network when using network_mode:host on runit systems. 2026-11-02 20:51:16 -07:00
me 4da671c40e llm, do not try to pull local image. 2026-11-02 16:19:16 -07:00
me 4db955b32d llm, add more context to the Build process headers. 2026-11-02 15:32:54 -07:00
me c0a9d79776 llm, add note on how to compile KMP projects. 2026-11-02 15:28:20 -07:00
me 4145a12637 i3, fix sunset-alarm not reporting errors. 2026-11-02 07:27:37 -07:00
me c23bb1c06b i3, fix location on redshift to have a colon. 2026-11-02 06:52:42 -07:00
me a9b78dbba2 i3, change bedtime from 21 to 20 and generalize redshift location. 2026-11-01 20:09:07 -07:00
me a714a26058 llm, mention that the release build needs filtered on v8a. 2026-11-01 15:26:45 -07:00
me d15b22ec26 llm, continue editing AGENTS based on findings when fixing more Android projects. 2026-11-01 09:56:30 -07:00
me 482d3072f5 llm, move the open-terminal container name up. 2026-11-01 08:10:42 -07:00
me 609edd6c3b llm, refactor the AGENTS version section. 2026-11-01 08:04:22 -07:00
me 1ded62a3d4 llm, update a few versions for Android and Flutter projects, as well as add the paths to where they are set and an example of what they look like. 2026-11-01 06:58:31 -07:00
me 0303a1c091 llm, change namespace on open-terminal build in case it does ever get uploaded. 2026-11-01 06:39:05 -07:00
me 10b21ac49b i3, add logging for sunset-alarm, add an annoyance for bedtime. 2026-11-01 05:59:36 -07:00
me 7efa7f1b91 llm, refactor which models are still relevent to install. 2026-11-01 05:47:15 -07:00
me d3a5946232 llm, add a function which deletes models that get put into the removal array. 2026-10-31 20:24:09 -07:00
me 46890d0d16 llm, stop mounting resolv.conf on containers, they sometimes get stale versions and files do not stay up tp date, let network_mode host handle it. 2026-10-31 09:29:45 -07:00
me 9073dfc597 docker, stop making the DNS file, the nameservers seem to fail even on network_mode host, unsure what else would be needed to get them to resolve. 2026-10-31 09:28:57 -07:00
me f3d9f088c7 llm, add mistral-small and see it if't truly the v4 MoE. 2026-10-31 08:21:18 -07:00
me 3c10415347 update, improve output of skipping NPM. 2026-10-31 08:07:19 -07:00
me 26dc61ebbf ai, add the command for the most recent test. 2026-10-31 07:54:46 -07:00
me 33755480bb ai, add some more benchmark results and make the tables per-model for easier reading. 2026-10-31 07:53:38 -07:00
me 35783422a3 i3, change sunset timer to actually be based on AZ sunset. 2026-10-30 21:19:56 -07:00
me d681c3f447 i3, fix sunset-timer not being able to show alert. 2026-10-30 21:17:20 -07:00
me a31cad1f42 open-webui, fix the network for this as well by mounting the host's resolv.conf directly. 2026-10-30 21:04:22 -07:00
me 788a723690 llm, go back to using host mode, seems to work as long as daemon.json exists with DNS servers, could not find a combination of the named network which worked well. 2026-10-30 20:55:11 -07:00
me 6ed4f284c0 i3, officially add Sunset Alarm, just from Code for now. 2026-10-30 20:34:02 -07:00
me 59b4343ec2 open-terminal, more attemots to get the container access to the Internet (DNS). 2026-10-30 20:26:12 -07:00
me af64e47519 ai, further scope Coder personality. 2026-10-30 19:57:45 -07:00
me e2c18a5cfc llm, do a few more things to try to get open-terminal DNS-ready more consistently. 2026-10-30 19:55:30 -07:00
me 556f483aaa roleplays, add an even smaller lang (16k ctx, 10k compact) and re-enable the 128k and 256k versions of code since some projects are actually getting big and keep compacting before even responding.. 2026-10-30 17:54:53 -07:00
10 changed files with 838 additions and 286 deletions

No files matched your search

+7 -6
View File
@@ -270,12 +270,13 @@
update_npm: |
## Let's let the distro package managers handle this, otherwise may end up
## breaking dependencies or causing other system weirdness. No thanks! :)
# if [[ `which npm` ]]; then
# echo "*** NPM ***" &&
# sudo npm update -g
# echo -e "\n"
# fi
echo "*** Skipping NPM ***"
if [[ `which npm` && 1 == 0 ]]; then
echo "*** NPM ***" &&
sudo npm update -g
echo -e "\n"
else
echo -e "*** Skipping NPM ***\n\n"
fi
# Flatpaks
- name: General | Facts | Package | Update Command | Flatpak | Check
+1 -1
View File
@@ -69,7 +69,7 @@ sleep 5
echo "*** Creating backup at '$BACKUP2' ***"
sudo zip -rv "$BACKUP2" \
/root /home /srv/sftp \
/root /home \
-x "*/.gradle/" -x "*/app/build/*"
status="$?"
+9 -2
View File
@@ -398,7 +398,7 @@ exec_always --no-startup-id "sleep 00; killall pipewire wireplumber pipewire-pul
exec_always --no-startup-id "sleep 01; pipewire >~/Reports/pipewire.log 2>&1 &"
exec_always --no-startup-id "sleep 02; wireplumber >~/Reports/wireplumber.log 2>&1 &"
exec_always --no-startup-id "sleep 03; pipewire-pulse >~/Reports/pipewire-pulse.log 2>&1 &"
exec --no-startup-id "sleep 04; bash -c 'source /usr/local/bin/volume.function && volume 25'"
exec --no-startup-id "sleep 04; bash -c 'source /usr/local/bin/volume.function && volume 75'"
# Wallpaper
exec_always --no-startup-id feh --recursive --randomize --bg-fill ~/Pictures/Wallpapers
@@ -412,7 +412,7 @@ exec_always --no-startup-id bash -c 'pkill -ef "bash `which battery_nag.sh`" >~/
# Redshift
#exec_always --no-startup-id "killall redshift-gtk; redshift-gtk"
#exec_always --no-startup-id "killall redshift; redshift -l 35.19540:-111.65720 -t 6500K:1100K"
exec_always --no-startup-id "killall redshift; killall redshift-gtk; sleep 1; redshift -x; redshift-gtk -l 35.19540:-111.65720 -t 6500K:1100K"
exec_always --no-startup-id "killall redshift; killall redshift-gtk; sleep 1; redshift -x; redshift-gtk -l 32:-111 -t 6500K:1100K"
# Allow locking the session.
#set $AGENT pkttyagent
@@ -442,3 +442,10 @@ set $refresh_i3status killall -SIGUSR1 i3status
#bindsym XF86AudioLowerVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ -10% && $refresh_i3status
#bindsym XF86AudioMute exec --no-startup-id pactl set-sink-mute @DEFAULT_SINK@ toggle && $refresh_i3status
#bindsym XF86AudioMicMute exec --no-startup-id pactl set-source-mute @DEFAULT_SOURCE@ toggle && $refresh_i3status
# Sunset Alarm
#exec_always --no-startup-id "killall sunset-alarm; /home/ling/Code/sunset_alarm_cli/sunset-alarm -t 20:00 -m 30 > ~/Reports/sunset-alarm.log 2>&1"
exec_always --no-startup-id "killall sunset-alarm; /home/ling/Code/sunset_alarm_cli/sunset-alarm -l 32:-111 -m 30 > ~/Reports/sunset-alarm.log 2>&1"
# Bedtime ;)
exec --no-startup-id "while true; do if [[ `date +'%H'` -ge 20 ]]; then fyi -w -u critical 'Bedtime' 'Go to sleep! >:)'; fi; sleep 150; done"
+85 -14
View File
@@ -662,7 +662,7 @@
"background_image_data": null
},
{
"version_id": "70a6bcc2-7a7f-4446-bd73-f2433c34af3c",
"version_id": "ce2ae15a-6804-4c63-9f3b-6634f8bf3806",
"id": "coder-moe-64k",
"user_id": "2e2e7554-11f1-4047-8ca4-b04070ccc704",
"base_model_id": "qwen3.6:35b",
@@ -672,7 +672,8 @@
"num_ctx": 64000,
"num_thread": 4,
"system": "Please use the attached Knowledge Base files as your personality.",
"compact_token_threshold": 48000
"compact_token_threshold": 48000,
"keep_alive": "0"
},
"meta": {
"profile_image_url": "/static/favicon.png",
@@ -722,7 +723,7 @@
},
"access_grants": [],
"is_active": true,
"updated_at": 1792987522,
"updated_at": 1793407717,
"created_at": 1792798618,
"background_image_data": null
},
@@ -792,7 +793,7 @@
"background_image_data": null
},
{
"version_id": "e5df99a2-6b1a-446f-b714-65b74740022c",
"version_id": "f7b2b0c3-6461-492c-b5e5-42586a381e94",
"id": "code-moe-128k",
"user_id": "2e2e7554-11f1-4047-8ca4-b04070ccc704",
"base_model_id": "qwen3.6:35b",
@@ -802,7 +803,8 @@
"num_ctx": 128000,
"num_thread": 4,
"system": "Please use the attached Knowledge Base files as your personality.",
"compact_token_threshold": 96000
"compact_token_threshold": 96000,
"keep_alive": "0"
},
"meta": {
"profile_image_url": "/static/favicon.png",
@@ -851,13 +853,13 @@
]
},
"access_grants": [],
"is_active": false,
"updated_at": 1792949673,
"is_active": true,
"updated_at": 1793407741,
"created_at": 1792896373,
"background_image_data": null
},
{
"version_id": "e48d06af-e6c0-4034-9506-f2e77030fe00",
"version_id": "592740ae-99a1-4534-b8e1-97338424d720",
"id": "code-moe-256k",
"user_id": "2e2e7554-11f1-4047-8ca4-b04070ccc704",
"base_model_id": "qwen3.6:35b",
@@ -867,7 +869,8 @@
"num_ctx": 999999,
"num_thread": 4,
"system": "Please use the attached Knowledge Base files as your personality.",
"compact_token_threshold": 32000
"compact_token_threshold": 192000,
"keep_alive": "0"
},
"meta": {
"profile_image_url": "/static/favicon.png",
@@ -916,8 +919,8 @@
]
},
"access_grants": [],
"is_active": false,
"updated_at": 1792984273,
"is_active": true,
"updated_at": 1793407763,
"created_at": 1792896428,
"background_image_data": null
},
@@ -1166,7 +1169,7 @@
"background_image_data": null
},
{
"version_id": "3979937f-a787-4e01-ac72-f55ddd0ebf17",
"version_id": "769e5084-3641-4c5c-90d9-0c58f0658227",
"id": "lang-32k",
"user_id": "2e2e7554-11f1-4047-8ca4-b04070ccc704",
"base_model_id": "qwen3.5:35b",
@@ -1176,7 +1179,8 @@
"custom_params": {},
"num_thread": 4,
"num_ctx": 32000,
"compact_token_threshold": 24000
"compact_token_threshold": 24000,
"keep_alive": "0"
},
"meta": {
"profile_image_url": "/static/favicon.png",
@@ -1227,8 +1231,75 @@
},
"access_grants": [],
"is_active": true,
"updated_at": 1793328802,
"updated_at": 1793370109,
"created_at": 1792988144,
"background_image_data": null
},
{
"version_id": "4ce3e85b-2d53-4605-a9c9-e370715c813a",
"id": "lang-16k",
"user_id": "2e2e7554-11f1-4047-8ca4-b04070ccc704",
"base_model_id": "qwen3.5:35b",
"name": "Lang [MoE,4-16K,TBD]",
"params": {
"system": "Please use the attached Knowledge Base files as your personality.",
"custom_params": {},
"num_thread": 4,
"num_ctx": 16000,
"compact_token_threshold": 10000,
"keep_alive": "0"
},
"meta": {
"profile_image_url": "/static/favicon.png",
"background_image_url": null,
"description": null,
"i18n": null,
"capabilities": {
"file_context": true,
"vision": true,
"file_upload": true,
"web_search": true,
"image_generation": true,
"code_interpreter": true,
"terminal": true,
"citations": true,
"status_updates": true,
"usage": true,
"memory": true,
"builtin_tools": true
},
"knowledge": [
{
"id": "120fa5c0-7f02-4cf3-a136-07b92b042d48",
"name": "Base.md",
"type": "file"
},
{
"id": "bb929f41-18c0-4177-8139-fabfde2b8235",
"name": "Language.md",
"type": "file"
}
],
"voice": null,
"voice_avatar": null,
"suggestion_prompts": null,
"tags": [
{
"name": "language"
},
{
"name": "general"
}
],
"defaultFeatureIds": [
"web_search",
"image_generation"
]
},
"access_grants": [],
"is_active": true,
"updated_at": 1793407973,
"created_at": 1793407973,
"background_image_data": null
}
]
+37 -1
View File
@@ -17,10 +17,30 @@
ansible.builtin.set_fact:
tunnel_service_name: tunnel
- name: General | Tunnel | Packages [pacman]
ansible.builtin.package:
name:
- openbsd-netcat
state: present
when: ansible_pkg_mgr == "pacman"
- name: General | Tunnel | Packages [apt]
ansible.builtin.package:
name:
- netcat-openbsd
state: present
when: ansible_pkg_mgr == "apt"
- name: General | Tunnel | runit
block:
- name: General | Tunnel | runit | mkdir | /etc/sv
ansible.builtin.file:
path: /etc/sv/{{ tunnel_service_name }}
state: directory
mode: "0755"
- name: General | Tunnel | runit | mkdir | /etc/sv log
ansible.builtin.file:
path: /etc/sv/{{ tunnel_service_name }}/log
state: directory
@@ -38,7 +58,23 @@
content: |
#!/bin/sh -e
exec 2>&1
exec chpst -u {{ user }} ssh -v -N \
# Health check to ensure connection does not go stale.
while true; do
sleep 300
echo -n "RUN-LOOP: "
nc -zv {{ tunnel_remote_host }} {{ tunnel_remote_port }}
status="$?"
echo "RUN-LOOP: Port check returned ${status}."
if [[ "$status" != 0 ]]; then
echo "RUN-LOOP: Restarting service."
sv restart {{ tunnel_service_name }}
fi
echo "RUN-LOOP: Going back to sleep."
done &
# Do not use `exec` here otherwise the loop may get killed.
chpst -u {{ user }} ssh -v -N \
-R {{ tunnel_remote_port }}:localhost:{{ tunnel_local_port }} \
-p {{ tunnel_ssh_port }} {{ tunnel_remote_host }}
mode: "0755"
@@ -62,6 +62,15 @@ These have been added your PATH via `/home/user/.bashrc`:
- `$FLUTTER_HOME/bin`
- `$JAVA_HOME/bin`
We focus on using free and open source technologies from community based
projects. Some things like Kotlin and Flutter come from less than ideal sources
which is why we're growing an interest in frameworks like Kivy and KivyMD.
If we ever need to do Internet activities, use dns.mullvad.net (194.242.2.2) for
DNS, hyperling.com and mullvad.net to validate Internet is working, and can use
1.0.0.1 and 1.1.1.1 from Cloudflare as a last resort, but not any big tech IPs.
#### Quick Developer
Handles code changes with simpler technologies, preferring minimal changes, and
@@ -145,6 +154,8 @@ $ fastfetch
```
$ export QUIET=true
$ ollama-test "64000 300000" "4 7 0" 0 "qwen3.5:35b qwen3.6:35b qwen3.8:27b devstral-small-2:24b"
```
| Model | HDD | Context | RAM | Threads | iGPU | Processor | Speed (t/s) | Time (s) |
| :------------------------ | -----: | -------: | -----: | ------: | ---: | --------: | ----------: | -------: |
| qwen3.5:35b | 22GB | 64000 | 23GB | 4 | 0 | 100%CPU | 13.36 | 61 |
@@ -153,26 +164,70 @@ $ ollama-test "64000 300000" "4 7 0" 0 "qwen3.5:35b qwen3.6:35b qwen3.8:27b devs
| qwen3.5:35b | 22GB | 262144 | 28GB | 4 | 0 | 100%CPU | 13.69 | 70 |
| qwen3.5:35b | 22GB | 262144 | 28GB | 7 | 0 | 100%CPU | 12.66 | 36 |
| qwen3.5:35b | 22GB | 262144 | 28GB | 0 | 0 | 100%CPU | 11.80 | 38 |
| Model | HDD | Context | RAM | Threads | iGPU | Processor | Speed (t/s) | Time (s) |
| :------------------------ | -----: | -------: | -----: | ------: | ---: | --------: | ----------: | -------: |
| qwen3.6:35b | 22GB | 64000 | 22GB | 4 | 0 | 100%CPU | 12.57 | 29 |
| qwen3.6:35b | 22GB | 64000 | 22GB | 7 | 0 | 100%CPU | 13.84 | 27 |
| qwen3.6:35b | 22GB | 64000 | 22GB | 0 | 0 | 100%CPU | 12.84 | 32 |
| qwen3.6:35b | 22GB | 262144 | 24GB | 4 | 0 | 100%CPU | 13.68 | 32 |
| qwen3.6:35b | 22GB | 262144 | 24GB | 7 | 0 | 100%CPU | 13.52 | 30 |
| qwen3.6:35b | 22GB | 262144 | 24GB | 0 | 0 | 100%CPU | 13.18 | 29 |
| Model | HDD | Context | RAM | Threads | iGPU | Processor | Speed (t/s) | Time (s) |
| :------------------------ | -----: | -------: | -----: | ------: | ---: | --------: | ----------: | -------: |
| qwen3.8:27b | 17GB | 64000 | 19GB | 4 | 0 | 100%CPU | 2.08 | 42 |
| qwen3.8:27b | 17GB | 64000 | 19GB | 7 | 0 | 100%CPU | 2.53 | 33 |
| qwen3.8:27b | 17GB | 64000 | 19GB | 0 | 0 | 100%CPU | 2.23 | 38 |
| qwen3.8:27b | 17GB | 262144 | 20GB | 4 | 0 | 100%CPU | 2.07 | 48 |
| qwen3.8:27b | 17GB | 262144 | 20GB | 7 | 0 | 100%CPU | 2.84 | 36 |
| qwen3.8:27b | 17GB | 262144 | 20GB | 0 | 0 | 100%CPU | 2.15 | 40 |
| Model | HDD | Context | RAM | Threads | iGPU | Processor | Speed (t/s) | Time (s) |
| :------------------------ | -----: | -------: | -----: | ------: | ---: | --------: | ----------: | -------: |
| devstral-small-2:24b | 15GB | 64000 | 26GB | 4 | 0 | 100%CPU | 2.25 | 94 |
| devstral-small-2:24b | 15GB | 64000 | 26GB | 7 | 0 | 100%CPU | 2.34 | 81 |
| devstral-small-2:24b | 15GB | 64000 | 26GB | 0 | 0 | 100%CPU | 2.29 | 88 |
| devstral-small-2:24b | 15GB | | | 4 | 0 | | 0.00 | 31 |
| devstral-small-2:24b | 15GB | | | 7 | 0 | | 0.00 | 27 |
| devstral-small-2:24b | 15GB | | | 0 | 0 | | 0.00 | 26 |
#### Context Speeds
Checking if the context affects the speed of the model. Seems negligible, way less than changing the threads or iGPU.
```console
$ ollama-test "16000 32000 64000 128000 256000 264000" "4" "0" "qwen3.5:35b qwen3.6:35b devstral-small-2:24b"
```
| Model | HDD | Context | RAM | Threads | iGPU | Processor | Speed (t/s) | Time (s) |
| :------------------------ | -----: | -------: | -----: | ------: | ---: | --------: | ----------: | -------: |
| qwen3.5:35b | 22GB | 16000 | 22GB | 4 | 0 | 100%CPU | 14.57 | 50 |
| qwen3.5:35b | 22GB | 32000 | 22GB | 4 | 0 | 100%CPU | 13.98 | 53 |
| qwen3.5:35b | 22GB | 64000 | 23GB | 4 | 0 | 100%CPU | 14.14 | 17 |
| qwen3.5:35b | 22GB | 128000 | 24GB | 4 | 0 | 100%CPU | 14.21 | 50 |
| qwen3.5:35b | 22GB | 256000 | 28GB | 4 | 0 | 100%CPU | 14.04 | 68 |
| qwen3.5:35b | 22GB | 262144 | 28GB | 4 | 0 | 100%CPU | 14.17 | 17 |
| Model | HDD | Context | RAM | Threads | iGPU | Processor | Speed (t/s) | Time (s) |
| :------------------------ | -----: | -------: | -----: | ------: | ---: | --------: | ----------: | -------: |
| qwen3.6:35b | 22GB | 16000 | 22GB | 4 | 0 | 100%CPU | 15.29 | 28 |
| qwen3.6:35b | 22GB | 32000 | 22GB | 4 | 0 | 100%CPU | 15.16 | 38 |
| qwen3.6:35b | 22GB | 64000 | 22GB | 4 | 0 | 100%CPU | 14.12 | 28 |
| qwen3.6:35b | 22GB | 128000 | 23GB | 4 | 0 | 100%CPU | 12.67 | 31 |
| qwen3.6:35b | 22GB | 256000 | 24GB | 4 | 0 | 100%CPU | 14.03 | 29 |
| qwen3.6:35b | 22GB | 262144 | 24GB | 4 | 0 | 100%CPU | 15.21 | 29 |
| Model | HDD | Context | RAM | Threads | iGPU | Processor | Speed (t/s) | Time (s) |
| :------------------------ | -----: | -------: | -----: | ------: | ---: | --------: | ----------: | -------: |
| devstral-small-2:24b | 15GB | 16000 | 17GB | 4 | 0 | 100%CPU | 2.90 | 87 |
| devstral-small-2:24b | 15GB | 32000 | 20GB | 4 | 0 | 100%CPU | 2.71 | 87 |
| devstral-small-2:24b | 15GB | 64000 | 26GB | 4 | 0 | 100%CPU | 2.36 | 91 |
| devstral-small-2:24b | 15GB | 128000 | 36GB | 4 | 0 | 100%CPU | 2.76 | 94 |
| devstral-small-2:24b | 15GB | 256000 | 58GB | 4 | 0 | 100%CPU | 2.30 | 100 |
| devstral-small-2:24b | 15GB | 264000 | 59GB | 4 | 0 | 100%CPU | 2.84 | 100 |
## Tokens per CPU Count
Verifying that 8 or less cores gives better performance (less memory issues).
+68 -238
View File
@@ -115,6 +115,16 @@
llm_removals:
##### QWEN #####
- { "purpose": ["chat"], "model": "qwen3:4b", "provider": "qwen_30_0040", "size_mb": 4000, "context": 123456 } # succeeded
### QWEN 3.0 Coder - Supposed to be better than 2.5 for machines that can handle it. Went okay, but better options now.
- { "purpose": ["code", "chat"], "model": "qwen3-coder:30b", "provider": "qwen_30_coder_0300_moe", "size_mb": "{{ llm_size_coef * 19000 }}", "context": 262144 }
- { "purpose": ["code", "chat"], "model": "qwen3-coder:420b", "provider": "qwen_30_coder_4200_moe", "size_mb": "{{ llm_size_coef * 290000 }}", "context": 262144 }
### QWEN 2.5 Coder - Ol'reliable! Did not seem to handle tools too well though. Defunitely not conversation.
- { "purpose": ["code"], "model": "qwen2.5-coder:0.5b", "provider": "qwen_25_coder_0005", "size_mb": "{{ llm_size_coef * 398 }}", "context": 32768 }
- { "purpose": ["code"], "model": "qwen2.5-coder:1.5b", "provider": "qwen_25_coder_0015", "size_mb": "{{ llm_size_coef * 986 }}", "context": 32768 }
- { "purpose": ["code"], "model": "qwen2.5-coder:3b", "provider": "qwen_25_coder_0030", "size_mb": "{{ llm_size_coef * 1900 }}", "context": 32768 }
- { "purpose": ["code"], "model": "qwen2.5-coder:7b", "provider": "qwen_25_coder_0070", "size_mb": "{{ llm_size_coef * 4700 }}", "context": 32768 }
- { "purpose": ["code"], "model": "qwen2.5-coder:14b", "provider": "qwen_25_coder_0140", "size_mb": "{{ llm_size_coef * 9000 }}", "context": 32768 }
- { "purpose": ["code"], "model": "qwen2.5-coder:32b", "provider": "qwen_25_coder_0320", "size_mb": "{{ llm_size_coef * 20000 }}", "context": 32768 }
##### Mistral #####
- { "purpose": ["code"], "model": "devstral:24b", "provider": "mistral_dev10_0240", "size_mb": "{{ llm_size_coef * 14000 }}", "context": 128000 } # succeeded
# https://ollama.com/library/mistral-small : Last Updated 2025-01-30, succeeded
@@ -122,11 +132,18 @@
- { "purpose": ["chat"], "model": "mistral-small:22b", "provider": "mistral_small30_0220", "size_mb": "{{ llm_size_coef * 13000 }}", "context": 128000 } # Yes, the smaller one has larger context.
# https://ollama.com/library/mistral-small3.1 : Last Update 2025-04-07, succeeded
- { "purpose": ["chat"], "model": "mistral-small3.1:24b", "provider": "mistral_small31_0240", "size_mb": "{{ llm_size_coef * 15000 }}", "context": 128000 }
# Supposedly ollama has it tagged at mistral-small with no params given. it's not on the site though. Let's find out!
# No, this is Mistral 3, as the website says. Ask Brave is wrooong.
- { "purpose": ["chat", "lang", "code"], "model": "mistral-small", "provider": "mistral_small40_1190", "size_mb": 60000 , "context": 256000 }
# https://ollama.com/library/mistral-nemo : Last Updated 2025-07-23
# Supposed to be a drop-in replacement for mistral:7b. Not really any more useful than the other options.
- { "purpose": ["chat", "lang"], "model": "mistral-nemo:12b", "provider": "mistral_nemo_0120", "size_mb": "{{ llm_size_coef * 7100 }}", "context": 128000 } # says 1000K in table but 128k in desc, going with desc.
llm_choices:
##### QWEN #####
### QWEN >3.5 - Need to try!
# Supposedly great for coding over any previous version.
# Prefer 27b (dense) over anything higher which likely uses MoE (essentially only uses 3b inside of a 35b, dumber but faster and potentially has access to more info).
# Supposedly great for coding over any previous version.
# Prefer 27b (dense) over anything higher which likely uses MoE (essentially only uses 3b inside of a 35b, dumber but faster and potentially has access to more info).
# Update: MoE actually runs really well on my workstation hardware, significantly faster than dense models, gives good results too.
# https://ollama.com/library/qwen3.8 : Last Updated 2026-09-25
# Known to overthink, suggested to prefer 3.6:27b unless setting temp to low/medium.
- { "purpose": ["code", "chat", "lang"], "model": "qwen3.8:27b", "provider": "qwen_38_0270", "size_mb": "{{ llm_size_coef * 18000 }}", "context": 262144 }
@@ -143,26 +160,16 @@
- { "purpose": ["chat", "code"], "model": "qwen3.5:27b", "provider": "qwen_35_0270", "size_mb": "{{ llm_size_coef * 17000 }}", "context": 262144 } # succeeded
- { "purpose": ["chat", "code"], "model": "qwen3.5:35b", "provider": "qwen_35_0350_moe", "size_mb": "{{ llm_size_coef * 22000 }}", "context": 262144 }
- { "purpose": ["chat", "code"], "model": "qwen3.5:122b", "provider": "qwen_35_1220_moe", "size_mb": "{{ llm_size_coef * 81000 }}", "context": 262144 }
### QWEN 3.0 Coder - Supposed to be better than 2.5 for machines that can handle it.
- { "purpose": ["code", "chat"], "model": "qwen3-coder:30b", "provider": "qwen_30_coder_0300_moe", "size_mb": "{{ llm_size_coef * 19000 }}", "context": 262144 }
- { "purpose": ["code", "chat"], "model": "qwen3-coder:420b", "provider": "qwen_30_coder_4200_moe", "size_mb": "{{ llm_size_coef * 290000 }}", "context": 262144 }
### QWEN 2.5 Coder - Ol'reliable!
- { "purpose": ["code"], "model": "qwen2.5-coder:0.5b", "provider": "qwen_25_coder_0005", "size_mb": "{{ llm_size_coef * 398 }}", "context": 32768 }
- { "purpose": ["code"], "model": "qwen2.5-coder:1.5b", "provider": "qwen_25_coder_0015", "size_mb": "{{ llm_size_coef * 986 }}", "context": 32768 }
- { "purpose": ["code"], "model": "qwen2.5-coder:3b", "provider": "qwen_25_coder_0030", "size_mb": "{{ llm_size_coef * 1900 }}", "context": 32768 }
- { "purpose": ["code"], "model": "qwen2.5-coder:7b", "provider": "qwen_25_coder_0070", "size_mb": "{{ llm_size_coef * 4700 }}", "context": 32768 }
- { "purpose": ["code"], "model": "qwen2.5-coder:14b", "provider": "qwen_25_coder_0140", "size_mb": "{{ llm_size_coef * 9000 }}", "context": 32768 }
- { "purpose": ["code"], "model": "qwen2.5-coder:32b", "provider": "qwen_25_coder_0320", "size_mb": "{{ llm_size_coef * 20000 }}", "context": 32768 }
##### Mistral, Ministral, and Devstral - By a French company. #####
# mistral-small-4
# https://huggingface.co/unsloth/Mistral-Small-4-119B-2603-GGUF
# Supposed to be better than Qwen equivalents, it's basically mistral, mixtral, magistral, and devstral all in one.
# unsloth version is supposed to be the best quantization. UD-Q3_K_XL is supposed to take 64GB RAM, lol, while Q4_K_M would need 80+ GB.
# needs done via 'ollama create', fails with pull. https://github.com/ollama/ollama/issues/5245
# https://huggingface.co/unsloth/Mistral-Small-4-119B-2603-GGUF
# Supposed to be better than Qwen equivalents, it's basically mistral, mixtral, magistral, and devstral all in one.
# unsloth version is supposed to be the best quantization. UD-Q3_K_XL is supposed to take 64GB RAM, lol, while Q4_K_M would need 80+ GB.
# needs done via 'ollama create', fails with pull. https://github.com/ollama/ollama/issues/5245
- { "purpose": ["chat", "lang", "code"], "model": "hf.co/unsloth/Mistral-Small-4-119B-2603-GGUF:UD-Q3_K_XL", "provider": "mistral_small40_1190_unsloth_q3", "size_mb": "{{ llm_size_coef * 54800 }}", "context": 256000 }
# https://huggingface.co/mistralai/Mistral-Small-4-119B-2603 : 242GB unquantized, lol.
# https://huggingface.co/mistralai/Mistral-Small-4-119B-2603 : 242GB unquantized, lol.
- { "purpose": ["chat", "lang", "code"], "model": "hf.co/mistralai/Mistral-Small-4-119B-2603", "provider": "mistral_small40_1190", "size_mb": "{{ llm_size_coef * 242000 }}", "context": 256000 }
# https://huggingface.co/unsloth/Mistral-Small-4-119B-2603 : 121GB, A6B MoE, hmmm!
# https://huggingface.co/unsloth/Mistral-Small-4-119B-2603 : 121GB, A6B MoE, hmmm!
- { "purpose": ["chat", "lang", "code"], "model": "hf.co/unsloth/Mistral-Small-4-119B-2603", "provider": "mistral_small40_1190_unsloth_a6b", "size_mb": "{{ llm_size_coef * 121000 }}", "context": 256000 }
# https://ollama.com/library/devstral-small-2 : Last Updated 2025-12-13
# Most recommended in Mistral family for agentic coding.
@@ -178,18 +185,7 @@
- { "purpose": ["chat", "lang"], "model": "ministral-3:3b", "provider": "mistral_mini30_0030", "size_mb": "{{ llm_size_coef * 3000 }}", "context": 256000 }
- { "purpose": ["chat", "lang"], "model": "ministral-3:8b", "provider": "mistral_mini30_0080", "size_mb": "{{ llm_size_coef * 6000 }}", "context": 256000 }
- { "purpose": ["chat", "lang"], "model": "ministral-3:14b", "provider": "mistral_mini30_0140", "size_mb": "{{ llm_size_coef * 9100 }}", "context": 256000 } # also rated super high for Croatian, gives more head room.
# https://ollama.com/library/mistral-nemo : Last Updated 2025-07-23
# Supposed to be a drop-in replacement for mistral:7b.
- { "purpose": ["chat", "lang"], "model": "mistral-nemo:12b", "provider": "mistral_nemo_0120", "size_mb": "{{ llm_size_coef * 7100 }}", "context": 128000 } # says 1000K in table but 128k in desc, going with desc.
##### TBD #####
### QWEN 2.5 - Older, but does not have "thinking", tempting!
#- qwen2.5:0.5b
#- qwen2.5:1.5b
#- qwen2.5:3b
#- qwen2.5:7b
#- qwen2.5:14b
#- qwen2.5:32b
#- qwen2.5:72b
### Z.ai
#- GLM-5.x
#- glm4-flash
@@ -448,18 +444,12 @@
# Ensure cleanup on any exit (normal or signal from runit).
trap 'kill "$LOOP_PID" 2>/dev/null; wait "$LOOP_PID" 2>/dev/null' EXIT
# Create a network for associated programs.
net={{ llm_docker_network }}
docker network inspect $net >/dev/null 2>&1 || \
docker network create $net
# Start the open-webui program.
set -e
docker run \
--name open-webui --network $net \
-e PORT={{ open_webui_port }} \
-p {{ open_webui_port }}:{{ open_webui_port }} \--add-host=host.docker.internal:host-gateway \
-e OLLAMA_BASE_URL=http://host.docker.internal:11434 \
--name open-webui \
--network host -e PORT={{ open_webui_port }} \
-e OLLAMA_BASE_URL=http://0.0.0.0:11434 \
{{ ("-e HF_TOKEN=" ~ hf_token) if hf_token else '' }} \
-e WEBUI_SECRET_KEY={{ open_webui_key }} \
-e ENABLE_QUERIES_CACHE=True \
@@ -505,6 +495,17 @@
# Open Terminal - Start #
- name: Workstation | Linux | Software | LLMs | Sandbox
ansible.builtin.import_tasks: tasks/workstation/linux/software/ai/sandbox.yml
- name: Workstation | Linux | Software | LLMs | runit | open-terminal | Facts
ansible.builtin.set_fact:
jdk_jvm: "{{ jdk_jvm | default('/usr/lib/jvm') }}"
jdk_etc: "{{ jdk_etc | default('/etc/java-openjdk') }}"
jdk_etc17: "{{ jdk_etc17 | default('/etc/java17-openjdk') }}"
jdk_etc21: "{{ jdk_etc21 | default('/etc/java21-openjdk') }}"
jdk_etc25: "{{ jdk_etc25 | default('/etc/java25-openjdk') }}"
- name: Workstation | Linux | Software | LLMs | runit | open-terminal | Dir | /etc/sv
ansible.builtin.file:
name: "/etc/sv/open-terminal/log"
@@ -526,210 +527,18 @@
owner: root
mode: "0755"
- name: Workstation | Linux | Software | LLMs | runit | open-terminal | AI-Sandbox | Dir
ansible.builtin.file:
dest: "{{ user_user.home }}/AI-Sandbox"
state: directory
owner: "{{ user }}"
group: "{{ user }}"
mode: "0755"
- name: Workstation | Linux | Software | LLMs | runit | open-terminal | AI-Sandbox | Env
ansible.builtin.blockinfile:
path: "{{ user_user.home }}/AI-Sandbox/{{ item }}"
marker: "# {mark} | MANAGE BY ANSIBLE | Env Vars"
content: |
if [[ -d "$HOME/bin" ]]; then
export PATH="$HOME/bin:$PATH"
fi
export ANDROID_HOME="{{ user_user.home }}/SDKs/Android/Sdk"
export GRADLE_USER_HOME={{ user_user.home }}/.gradle
export PATH="$ANDROID_HOME/platform-tools:$PATH"
export PATH="$ANDROID_HOME/cmdline-tools/latest/bin:$PATH"
export FLUTTER_HOME="{{ user_user.home }}/SDKs/Flutter/flutter"
export PUB_CACHE={{ user_user.home }}/.pub-cache
export PATH="$FLUTTER_HOME/bin:$PATH"
export JAVA_HOME="{{ user_user.home }}/SDKs/Java"
export PATH="$JAVA_HOME/bin:$PATH"
create: false
backup: false
owner: "{{ user }}"
group: "{{ user }}"
mode: "0755"
loop:
- ".bashrc"
- name: Workstation | Linux | Software | LLMs | runit | open-terminal | AI-Sandbox | Defaults
ansible.builtin.set_fact:
jdk_jvm: "{{ jdk_jvm | default('/usr/lib/jvm') }}"
jdk_etc: "{{ jdk_etc | default('/etc/java-openjdk') }}"
jdk_etc17: "{{ jdk_etc17 | default('/etc/java17-openjdk') }}"
jdk_etc21: "{{ jdk_etc21 | default('/etc/java21-openjdk') }}"
jdk_etc25: "{{ jdk_etc25 | default('/etc/java25-openjdk') }}"
- name: Workstation | Linux | Software | LLMs | runit | open-terminal | AI-Sandbox | AGENTS.md
ansible.builtin.copy:
dest: "{{ user_user.home }}/AI-Sandbox/AGENTS.md"
content: |
# Environment
You are running in a Docker container called Open Terminal. We are
communicating via Open WebUI, also being run in a Docker
container. You are the user `user` and have been granted access to
the designer's Code and SDKs via mount at `{{ user_user.home }}`.
Host system is typically (but not always) a systemd-free distro
such as Artix or Devuan. User likes the `runit` service manager.
`elogind` is used rather than systemd's logind. Desktop is i3 and
display manager is lightdm. Servers are run on Debian and Docker
containers are typically debian:trixie-slim with a Dockerfile
called by compose.yml which adds the necessary packages, sometimes
building from source if the Debian executable is too old.
If the `$GOT_EM` environment variable is `true` then all the
necessary packages for compiling Android and Flutter were
installed. If it is `false` then they were not installed, and
compiling will fail. Please check this before trying and alert me
if they need added. If we don't have Internet, then ask me to
compile or run whatever command is needed on the host system.
# Rules
Never use any `git` subcommands that change the repo, including
but not limited to `add`, `commit`, `pull`, `push`, `branch`,
`switch`, etc. The user is who controls the respository changes.
You may use informational git subcommands such as `git status`,
and may occasionally be asked to run `git clone` type commands.
If any programs need installed in order to work on a project, we
need to document that in an `install.sh` script, as well as add it
to `~/PACKAGES.txt` so that we can ensure they stay installed.
`install.sh` scripts should be for both `apt` systems (Debian,
Ubuntu) and pacman system (Arch, Artix). using distribution
package managers is preferable over `pip` and `npm` when
possible, unless the project is actually Python or Node.js.
The user manages the `{{ user_user.home }}/SDKs` directory. Do not
modify it. Instead, ask if anything needs updated or added.
Never manually edit, modify, delete, alter, replace, etc any
files under system folders such as `/usr`. Anything under `/` is
managed by the system. If you need assistance changing anything
such as `/usr/lib/jvm`, please ask the user and halt all further
operations until you have received feedback.
# Effort
It is never okay to brute force a solution if something is not
working well. it is better to ask the user for assistance or alert
them that you've encountered blockers and then cease the process
until you've received feedback. This especially relates to when
system errors occur which are not related to the source code, such
as a compiler failing to be found or an SDK version mismatch. If
the error is with the source code though, troubleshooting and code
changes should continue until the program is compiling properly.
For CLI projects such as script languages, the final result should
always be tested both to run successfully and have the proper
output. All test cases should be analyzed and walked through,
which will help ensure all the requirements have been met.
For GUI programs (such as Android, Flutter, Kotlin Multiplatform,
Kivy, etc), the project should be tested to both compile & build
successfully and also generate the proper installation file (APK,
Linux Bundle). Once that is confirmed, the user/desginer will test
that the application meets the proper requirements.
# Preferences
You have free reign over your home directory. Feel free to
create memory files or anything else which would benefit you.
Everything we create should have both Desktop Linux and Android
in mind. Windows, MacOS, and iOS will never be compiled for, but
if we can do things in a way which makes it easy for others to
fork the project and add the support themselves, then that's best.
# Versions
These are the versions of plugins and languages we need to use.
If you know of an important upgrade from them, please let me know.
## Android / Flutter
- Gradle: 9.8.0
- AGP: 9.4.1
- Kotlin: 2.4.20
- Java: JDK 17
- Flutter (plugin loader): 1.0.0
Regardless of whether AGP bundles Kotlin, we need to specify it to
avoid things like "Your project's Kotlin version (2.2.10) is lower
than Flutter's minimum supported version of 2.2.20. Please upgrade
your Kotlin version." This is exactly why we use these versions,
plus it helps document what's actually being used over guessing.
backup: false
owner: "{{ user }}"
group: "{{ user }}"
mode: "0755"
- name: Workstation | Linux | Software | LLMs | runit | open-terminal | Script | Compose YAML
ansible.builtin.copy:
dest: /usr/local/etc/open-terminal/compose.yml
content: |
#exec docker run \
# --name open-terminal \
# --network=host \
# -v {{ user_user.home }}/AI-Sandbox:/home/user \
# -v {{ user_user.home }}/Code:{{ user_user.home }}/Code \
# -v {{ user_user.home }}/SDKs:{{ user_user.home }}/SDKs \
# -v {{ jdk_jvm }}:{{ jdk_jvm }}:ro \
# -v {{ jdk_etc }}:{{ jdk_etc }}:ro \
# -v {{ jdk_etc17 }}:{{ jdk_etc17 }}:ro \
# -v {{ jdk_etc21 }}:{{ jdk_etc21 }}:ro \
# -v {{ jdk_etc25 }}:{{ jdk_etc25 }}:ro \
# -v /etc/hosts:/etc/hosts:ro \
# -v {{ user_user.home }}/.gradle:{{ user_user.home }}/.gradle \
# -v {{ user_user.home }}/.pub-cache:{{ user_user.home }}/.pub-cache \
# -e OPEN_TERMINAL_FILE_BROWSER_ROOT="/home/user" \
# -e OPEN_TERMINAL_API_KEY="{{ open_terminal_key }}" \
# -e OPEN_TERMINAL_PACKAGES="$packages" \
# -e GOT_EM="$GOT_EM" \
# $image run --port {{ open_terminal_port }}
networks:
{{ llm_docker_network }}:
name: {{ llm_docker_network }}
external: true
services:
open-terminal:
container_name: open-terminal
build:
context: ./
image: hyperling-open-terminal:latest
container_name: open-terminal
ports:
- {{ open_terminal_port }}:{{ open_terminal_port }}
networks:
- {{ llm_docker_network }}
#dns:
# ## Mullvad
# ## (https://mullvad.net/en/help/dns-over-https-and-dns-over-tls)
# #- 194.242.2.9 # all.dns.mullvad.net
# ##- 194.242.2.8 # not real (yet?)
# ##- 194.242.2.7 # not real (yet?)
# #- 194.242.2.6 # family.dns.mullvad.net
# #- 194.242.2.5 # extended.dns.mullvad.net
# #- 194.242.2.4 # base.dns.mullvad.net
# #- 194.242.2.3 # adblock.dns.mullvad.net
# - 194.242.2.2 # dns.mullvad.net
# #- 194.242.2.1 # not real (yet?)
# #- 194.242.2.0 # not real (yet?)
# ## Cloudflare
# - 1.0.0.1
# - 1.1.1.1
image: hyperling/open-terminal:latest
pull_policy: never
network_mode: host
command: run --port {{ open_terminal_port }}
environment:
- OPEN_TERMINAL_FILE_BROWSER_ROOT=/home/user
@@ -747,7 +556,6 @@
- {{ jdk_etc17 }}:{{ jdk_etc17 }}:ro
- {{ jdk_etc21 }}:{{ jdk_etc21 }}:ro
- {{ jdk_etc25 }}:{{ jdk_etc25 }}:ro
#- /etc/resolv.conf:/etc/resolv.conf:ro
- {{ user_user.home }}/.gradle:{{ user_user.home }}/.gradle
- {{ user_user.home }}/.pub-cache:{{ user_user.home }}/.pub-cache
owner: root
@@ -991,7 +799,6 @@
loop:
- { 'name': "{{ ollama }}" , 'status': "{{ ollama_enabled }}" }
- { 'name': "{{ zeroclaw }}" , 'status': "{{ zeroclaw_enabled }}" }
- { 'name': 'docker' , 'status': true }
- { 'name': 'open-webui' , 'status': "{{ open_webui_enabled }}" }
- { 'name': 'open-terminal' , 'status': "{{ open_terminal_enabled }}" }
- { 'name': 'swap-stopper' , 'status': true }
@@ -1034,17 +841,24 @@
path: "{{ user_user.home }}/{{ item }}"
marker: "# {mark} ANSIBLE MANAGED BLOCK | ollama | Manual Script"
content: |
function ollama_llms() {
function llm_installs() {
{% for llm in llm_installs %}
echo "{{ llm.model }}"
{% endfor %}
}
function llm_removals() {
{% for llm in llm_removals %}
echo "{{ llm.model }}"
{% endfor %}
}
function ollama_pull() {
echo "Manually Pulling Models"
for model in `ollama_llms`; do
for model in `llm_installs`; do
echo -e "\n\n Starting 'ollama pull $model' \n\n"
ollama pull $model
status=$?
@@ -1057,6 +871,22 @@
alias pull-models="ollama_pull "
alias pull-ai="ollama_pull "
function ollama_clean() {
echo "Cleaning Models"
for model in `llm_removals`; do
echo -e "\n Removing '$model'"
ollama rm $model
done
echo "Done!"
}
alias ollama-clean="ollama_clean "
alias clean-ollama="ollama_clean "
alias clean-llms="ollama_clean "
alias clean-models="ollama_clean "
alias clean-ai="ollama_clean "
function ollama_chat() {
ollama run {{ 'qwen3.8:27b' if ansible_memtotal_mb > 32000 else 'qwen3.5:4b' }}
}
@@ -0,0 +1,496 @@
---
# Move the plays related to AGENTS.md to its own file since it is now so large.
- name: Workstation | Linux | Software | AI | Sandbox | Dir
ansible.builtin.file:
dest: "{{ user_user.home }}/AI-Sandbox"
state: directory
owner: "{{ user }}"
group: "{{ user }}"
mode: "0755"
- name: Workstation | Linux | Software | AI | Sandbox | Env
ansible.builtin.blockinfile:
path: "{{ user_user.home }}/AI-Sandbox/{{ item }}"
marker: "# {mark} | MANAGE BY ANSIBLE | Env Vars"
content: |
if [[ -d "$HOME/bin" ]]; then
export PATH="$HOME/bin:$PATH"
fi
export ANDROID_HOME="{{ user_user.home }}/SDKs/Android/Sdk"
export GRADLE_USER_HOME={{ user_user.home }}/.gradle
export PATH="$ANDROID_HOME/platform-tools:$PATH"
export PATH="$ANDROID_HOME/cmdline-tools/latest/bin:$PATH"
export FLUTTER_HOME="{{ user_user.home }}/SDKs/Flutter/flutter"
export PUB_CACHE={{ user_user.home }}/.pub-cache
export PATH="$FLUTTER_HOME/bin:$PATH"
export JAVA_HOME="{{ user_user.home }}/SDKs/Java"
export PATH="$JAVA_HOME/bin:$PATH"
create: false
backup: false
owner: "{{ user }}"
group: "{{ user }}"
mode: "0755"
loop:
- ".bashrc"
- name: Workstation | Linux | Software | AI | Sandbox | AGENTS.md
ansible.builtin.copy:
dest: "{{ user_user.home }}/AI-Sandbox/AGENTS.md"
content: |
# Environment
You are running in a Docker container called Open Terminal. We are
communicating via Open WebUI, also being run in a Docker
container. You are the user `user` and have been granted access to
the designer's Code and SDKs via mount at `{{ user_user.home }}`.
Host system is typically (but not always) a systemd-free distro
such as Artix or Devuan. User likes the `runit` service manager.
`elogind` is used rather than systemd's logind. Desktop is i3 and
display manager is lightdm. Servers are run on Debian and Docker
containers are typically debian:trixie-slim with a Dockerfile
called by compose.yml which adds the necessary packages, sometimes
building from source if the Debian executable is too old.
If the `$GOT_EM` environment variable is `true` then all the
necessary packages for compiling Android and Flutter were
installed. If it is `false` then they were not installed, and
compiling will fail. Please check this before trying and alert me
if they need added. If we don't have Internet, then ask me to
compile or run whatever command is needed on the host system.
# Rules
Never use any `git` subcommands that change the repo, including
but not limited to `add`, `commit`, `pull`, `push`, `branch`,
`switch`, etc. The user is who controls the respository changes.
You may use informational git subcommands such as `git status`,
and may occasionally be asked to run `git clone` type commands.
If any programs need installed in order to work on a project, we
need to document that in an `install.sh` script, as well as add it
to `~/PACKAGES.txt` so that we can ensure they stay installed.
`install.sh` scripts should be for both `apt` systems (Debian,
Ubuntu) and pacman system (Arch, Artix). using distribution
package managers is preferable over `pip` and `npm` when
possible, unless the project is actually Python or Node.js.
The user manages the `{{ user_user.home }}/SDKs` directory. Do not
modify it. Instead, ask if anything needs updated or added.
Never manually edit, modify, delete, alter, replace, etc any
files under system folders such as `/usr`. Anything under `/` is
managed by the system. If you need assistance changing anything
such as `/usr/lib/jvm`, please ask the user and halt all further
operations until you have received feedback.
# Effort
It is never okay to brute force a solution if something is not
working well. it is better to ask the user for assistance or alert
them that you've encountered blockers and then cease the process
until you've received feedback. This especially relates to when
system errors occur which are not related to the source code, such
as a compiler failing to be found or an SDK version mismatch. If
the error is with the source code though, troubleshooting and code
changes should continue until the program is compiling properly.
For CLI projects such as script languages, the final result should
always be tested both to run successfully and have the proper
output. All test cases should be analyzed and walked through,
which will help ensure all the requirements have been met.
For GUI programs (such as Android, Flutter, Kotlin Multiplatform,
Kivy, etc), the project should be tested to both compile & build
successfully and also generate the proper installation file (APK,
Linux Bundle). Once that is confirmed, the user/desginer will test
that the application meets the proper requirements.
# Preferences
You have free reign over your home directory. Feel free to
create memory files or anything else which would benefit you.
Everything we create should have both Desktop Linux and Android
in mind. Windows, MacOS, and iOS will never be compiled for, but
if we can do things in a way which makes it easy for others to
fork the project and add the support themselves, then that's best.
# Versions
These are the versions of plugins and languages we need to use.
If you know of an important upgrade from them, please let me know.
If you find that an application is already a newer version than
those listed here, that is acceptable, never attempt to downgrade
without explicitly asking the user first and having a good reason.
## Android / Flutter
- Gradle 9.8.2
- AGP 9.5.0
- Kotlin 2.4.21
- Java JDK 17
- Flutter Plugin Loader 1.0.0
- compileSdk 37
- targetSDK 37
Regardless of whether AGP bundles Kotlin, we need to specify it to
avoid things like "Your project's Kotlin version (2.2.10) is lower
than Flutter's minimum supported version of 2.2.20. Please upgrade
your Kotlin version." This is exactly why we use these versions,
plus it helps document what's actually being used over guessing.
Only the arm-v8a architecture needs included in the release
builds. x86 and others should continue to exist in the debug run.
This will help save space on local servers like Gitea and F-Droid.
If code for this does not exist, please add splitting or filtering
so that when the designer generates a signed APK it's only v8a.
Android : paths are from the project root.
Flutter : paths are under the folder `android`.
### All Android Project Types
#### ./gradle/wrapper/grade-wrapper.properties
```
distributionUrl=https\://services.gradle.org/distributions/gradle-9.8.2-bin.zip
```
#### ./settings.gradle.kts
```
id("com.android.application") version "9.5.0" apply false
id("org.jetbrains.kotlin.android") version "2.4.21" apply false
```
#### ./app/build.gradle.kts
```
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlin {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_17)
}
}
```
Also enable minify and shrink while in there.
```
buildTypes {
getByName("release") {
...
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
```
### Flutter Projects
#### ./settings.gradle.kts
```
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
```
### Native Kotlin Apps
These only apply to Android apps which are not Flutter, Kivy, etc.
#### Plugin Versions
##### ./gradle/libs.versions.toml
```
[versions]
agp = "9.5.0"
kotlin = "2.4.21"
coreKtx = "1.19.1"
junit = "4.13.2"
junitVersion = "1.3.0"
espressoCore = "3.7.0"
lifecycleRuntimeKtx = "2.11.0"
activityCompose = "1.13.0"
composeBom = "2026.09.00"
```
#### Kotlin Compose Fix
Also ensure Kotlin is coming from Compose and not Jetbrains.
##### ./gradle/libs.versions.toml
```
[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }
#jetbrainsKotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
kotlinCompose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
```
##### ./build.gradle.kts
```
plugins {
alias(libs.plugins.androidApplication) apply false
//alias(libs.plugins.jetbrainsKotlinAndroid) apply false
alias(libs.plugins.kotlinCompose) apply false
}
```
##### ./app/build.gradle.kts
```
plugins {
alias(libs.plugins.androidApplication)
//alias(libs.plugins.jetbrainsKotlinAndroid)
alias(libs.plugins.kotlinCompose)
}
```
# Build Processes
How to compile certain projects. Tools to prefer. If a language
or framework is not mentioned, then use the typical commands.
## Kotlin Multiplatform (KMP)
Used to create small native Android apps with the ability to also
run against Desktop Linux. APK size is the greatest benefit for
using KMP over something like Flutter or KivyMD.
### Kotlin Toolchain
This is the preferred build type when setting up new projects.
Please use `kotlin` rather than any `amper` commands. `amper` has
been deprecated and is intentionally not present on the system.
Examples:
```
# 1. Compile + link ALL targets (JVM, iOS, Android, native, etc.)
./kotlin build
# 2. (Optional) Run tests across all targets
./kotlin test
# 3. (Optional) Run all quality checks (tests + registered linters)
./kotlin check
```
### Gradle KMP
This is a legacy method, new projects will not be set up with it.
Examples:
```
# Compile all targets
./gradlew assemble
# Or more explicitly (if you want to be sure nothing is skipped):
./gradlew jvmJar assembleDebug assembleIosSimulatorArm64 # etc. per target
# Run all tests
./gradlew allTests
```
# Coding Conventions
Preferences related to how code should be written.
## All languages
If a value is going to be used more than once, even a small path or file
name, it should exist in a variable.
Relative shebangs such as `#!/usr/bin/env bash` and `#!/usr/bin/env node`
are always preferred over static shebangs such as `#!/bin/bash`, since
scripts are run across a multitude of different systems.
### Layout
Programs should be laid out in 5 sections.
- Variables
- Instantiate global variables and defaults used for parameters which
do not get passed an explicit value by the user.
- Functions
- Functions to be used throughout the program, including the Usage.
- Parameters / Validation
- Parse the parameters, validate the input, and assign any defaults.
- Main
- The primary logic of the program, completes the task at hand.
- Finish / Cleanup
- Typically just `exit 0`, but sometimes a summary of what was done.
All sections may not always apply, such as with Hugo websites. With
projects like Android apps this would apply to each individual function,
method, and class. If a section does not need anything, it can be blank.
```
public static void doThing(String thingName) {
// Variables //
String thingPrefix = "/place/for/thing/"
// Functions //
// Parameters //
if (thingName.isEmpty) {
Exception e = new Exception("No name passed!");
throw e;
}
// Main //
runStuff(thingPrefix + thingName);
// Finish //
}
```
The comments do not need to be included, this example is just as valid,
what maytters most is that the 5 section are done in order rather than
instantiating variable mid-scope.
```
public static void doThing(String thingName) {
String thingPrefix = "/place/for/thing/"
if (thingName.isEmpty) {
Exception e = new Exception("No name passed!");
throw e;
}
runStuff(thingPrefix + thingName);
}
```
`if` statements and loops start new scope, so they also need the layout
applied to them. Loops may sometimes require a variable assignment before
it begins which is completely okay and does not break the layout rule.
This example has a Variables, Validation, Main, and Finish section without
the use of labels or comments since the code itself is simple and small.
```
count=0
array="cats dogs giraffes rhinos horses"
last_animal=""
for animal in $array; do
if (( count >= 3 )); then
echo "That's enough! We finished at the ${last_animal}."
break;
fi
echo "We're looking at ${animal}."
last_animal=$animal
(( count++ ))
done
```
Providing the user's input in error messages is really helpful and can aid
their troubleshooting if things are not going according to expectations.
Example using Bash:
```
#!/usr/bin/env bash
### Variables ###
declare A B
typeset -i a b
### Functions ###
function usage() {
status="$1"
cat << EOF
Usage: add.sh -a NUM -b NUM [-h]
Adds two numbers and prints out the full equation.
Example:
$ add.sh -a 5 -b 25
5 + 25 = 30
EOF
exit $status
}
function add() {
num1="$1"
num2="$2"
sum=""
if [[ -z $num1 || -z $num2 ]]; then
echo "ERROR: Two numnbers must be passed."
fi
sum=$(( num1 + num2 ))
echo "${num1} + ${num2} = ${sum}"
}
### Parameters ###
while getopts ':a:b:h' opt; do
case $opt in
a) A="$OPTARG" ;;
b) B="$OPTARG" ;;
h) usage 0 ;;
*) echo "ERROR: Option $OPTARG not recognized." >&2 && usage 1 ;;
esac
done
if [[ -z "$A" || -z "$B" ]]; then
echo "ERROR: Both numbers need to be passed. A=${A} B=${B}" >&2
usage 2
fi
a="$A" b="$B"
if [[ "$a" != "$A" || "$b" != "$B" ]]; then
echo "ERROR: Values contain non-numeric data, please try again." >&2
echo "A=${A} B=${B}" >&2
usage 3
fi
### Main ###
add "$a" "$b"
### Finish ###
unset A B usage add
exit 0
```
## Bash
`[[ ]]` are preferred over `[ ]`, `test`, etc. `(( ))` are always fine.
When defining a function please use both the keyword `function` as well as
the `()`, such as `function myfunc() {}`.
When instantiating global variables, please use `typeset` or `declare`
rather than just `VAR1=""; VAR2=""`, such as:
```
declare VAR1="" VAR2="" BOOL="true" BOOL2="false"
typeset -i INT1=0 INT2=99
```
When doing colored output, `tput` is always preferred over literal values.
backup: false
owner: "{{ user }}"
group: "{{ user }}"
mode: "0755"
+80 -18
View File
@@ -33,22 +33,84 @@
owner: root
mode: '0755'
# This was causing the docker daemon to fail. Was trying to fix ports mappings.
#- name: Workstation | Linux | Software | Docker | Config | File
# ansible.builtin.copy:
# dest: /etc/docker/daemon.json
# content: |
# {
# "firewall-backend": "nftables"
# }
# backup: false
# owner: root
# mode: '0644'
# when: ansible_pkg_mgr == "pacman"
- name: Workstation | Linux | Software | Socker | Services | Enable
ansible.builtin.service:
name: "{{ item.name }}"
state: "{{ 'started' if item.status else 'stopped' }}"
enabled: "{{ item.status }}"
loop:
- { 'name': 'docker' , 'status': true }
- name: Workstation | Linux | Software | Docker | Config | File
ansible.builtin.file:
name: /etc/docker/daemon.json
state: absent
owner: root
mode: '0755'
- name: Workstation | Linux | Software | Docker | Network Sync | runit | Facts
ansible.builtin.set_fact:
docker_network_sync: "docker-network-sync"
- name: Workstation | Linux | Software | Docker | Network Sync | runit | Block
block:
- name: Workstation | Linux | Software | Docker | Network Sync | runit | /etc/sv
ansible.builtin.file:
name: "/etc/sv/{{ docker_network_sync }}/log"
state: directory
owner: root
mode: "0755"
- name: Workstation | Linux | Software | Docker | Network Sync | runit | /var/log
ansible.builtin.file:
name: "/var/log/{{ docker_network_sync }}"
state: directory
owner: "{{ user }}"
mode: "0755"
- name: Workstation | Linux | Software | Docker | Network Sync | runit | Run
ansible.builtin.copy:
dest: /etc/sv/{{ docker_network_sync }}/run
content: |
#!/bin/sh
# Ensure all containers using host network keep a correct resolv.conf.
exec 2>&1
set -e
while true; do
for c in $(docker container ls --filter network=host -q); do
echo "RUN: Container ID $c"
docker exec -i -u root $c sh -c 'tee /etc/resolv.conf' < /etc/resolv.conf
done
echo "RUN: Done, sleeping."
sleep 20
done
backup: false
owner: root
mode: '0755'
- name: Workstation | Linux | Software | Docker | Network Sync | runit | Finish
ansible.builtin.copy:
dest: /etc/sv/{{ docker_network_sync }}/finish
content: |
{{ runit_finish_sleep }}
mode: "0755"
- name: Workstation | Linux | Software | Docker | Network Sync | runit | Log
ansible.builtin.copy:
dest: /etc/sv/{{ docker_network_sync }}/log/run
content: |
#!/bin/sh -e
exec svlogd -tt /var/log/{{ docker_network_sync }}
mode: "0755"
- name: Workstation | Linux | Software | Docker | Network Sync | runit | Log Config
ansible.builtin.copy:
dest: /var/log/{{ docker_network_sync }}/config
content: |
{{ runit_log_config_1mb }}
mode: "0755"
- name: Workstation | Linux | Software | Socker | Services | Enable
ansible.builtin.service:
name: "{{ item.name }}"
state: "{{ 'started' if item.status else 'stopped' }}"
enabled: "{{ item.status }}"
loop:
- { 'name': '{{ docker_network_sync }}', 'status': true }
when: ansible_service_mgr == "runit"
-6
View File
@@ -21,12 +21,6 @@
- name: TEST | LLMs
block:
- name: Java
ansible.builtin.include_tasks: tasks/workstation/linux/software/java.yml
- name: Docker
ansible.builtin.include_tasks: tasks/workstation/linux/software/docker.yml
- name: LLM
ansible.builtin.include_tasks: tasks/workstation/linux/software/ai/llm.yml