Skip to content

Commit f8efcf2

Browse files
committed
docs: reset AGENTS.md to minimal header
1 parent 70cdb5c commit f8efcf2

File tree

17 files changed

+712
-918
lines changed

17 files changed

+712
-918
lines changed

.config/ags/AGENTS.md

Lines changed: 20 additions & 791 deletions
Large diffs are not rendered by default.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Architecture and Components
2+
3+
AGS runs in bundled mode for performance. All components in `lib/` are imported by `config-bundled.tsx` and run in a single GTK process.
4+
5+
Components (in `lib/`):
6+
7+
- `lib/confirm-dialog.tsx` - Confirmation dialog for high-impact operations
8+
- `lib/keyboard-switcher.tsx` - Keyboard layout switcher overlay
9+
- `lib/volume-indicator.tsx` - Volume change indicator with automatic monitoring
10+
- `lib/start-menu.tsx` - System start menu with update badges
11+
- `lib/window-switcher.tsx` - Alt+Tab window switcher with previews
12+
13+
Entry points:
14+
15+
- `config-bundled.tsx` - Main bundled configuration (imports all components)
16+
- `start-daemons.sh` - Boot script to start AGS in bundled mode
17+
18+
Bundled mode details:
19+
20+
- Each component window has its own namespace
21+
- CSS is applied during module loading
22+
- Components export to `globalThis` for communication
23+
- Single GTK process hosts all windows
24+
25+
File structure:
26+
27+
```
28+
.config/ags/
29+
├── lib/ # Component library (canonical source)
30+
│ ├── confirm-dialog.tsx
31+
│ ├── keyboard-switcher.tsx
32+
│ ├── volume-indicator.tsx
33+
│ ├── start-menu.tsx
34+
│ └── window-switcher.tsx
35+
├── config-bundled.tsx # Main entry point (imports from lib/)
36+
├── config.tsx # Stub (bundled mode required)
37+
└── start-daemons.sh # Boot script (runs config-bundled.tsx)
38+
```
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Best Practices
2+
3+
1. Prefer JSX over programmatic widget creation.
4+
2. Use the `setup` callback to capture widget references when you need imperative access.
5+
3. Set `namespace` on windows for Hyprland layer rules.
6+
4. Use enums not strings: `Astal.Layer.OVERLAY` not "overlay".
7+
5. Avoid invalid GTK CSS properties like `max-width` (use `min-width` or GTK properties).
8+
6. Kill `gjs` to reload CSS changes: `pkill gjs`.
9+
7. Use GTK Inspector (`ags inspect`) to debug styling.
10+
8. Use `keymode={Astal.Keymode.EXCLUSIVE}` for dialogs that need focus.
11+
9. Avoid `ignore_alpha` for solid backgrounds.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Commands and Setup
2+
3+
## Start bundled AGS
4+
5+
```bash
6+
./start-daemons.sh
7+
```
8+
9+
Manual start:
10+
11+
```bash
12+
ags run ~/.config/ags/config-bundled.tsx
13+
```
14+
15+
## IPC communication
16+
17+
```bash
18+
ags msg ags-bundled '{"window":"start-menu","action":"toggle"}'
19+
ags msg ags-bundled '{"window":"window-switcher","action":"next"}'
20+
```
21+
22+
## TypeScript type definitions
23+
24+
Type definitions for GObject Introspection libraries are auto-generated in `.config/ags/@girs/` (git-ignored).
25+
26+
Generate types (run after installing AGS or updating GTK libraries):
27+
28+
```bash
29+
cd ~/.config/ags
30+
ags types
31+
```
32+
33+
Regenerate when:
34+
35+
- Fresh system setup
36+
- After updating AGS or system GTK libraries
37+
- TypeScript shows "Cannot find module" errors for GI imports
38+
39+
## AGS command reference
40+
41+
```bash
42+
ags run <file.tsx>
43+
ags list
44+
ags request -i <instance-name> '<json-payload>'
45+
ags quit <instance-name>
46+
ags toggle <window-name>
47+
ags types
48+
ags bundle <file.tsx>
49+
ags inspect
50+
~/.config/ags/start-daemons.sh
51+
```

.config/ags/docs/agents/daemon.md

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# Daemon Lifecycle
2+
3+
## Overview
4+
5+
AGS runs as a single bundled process started at boot. All components are loaded into one process with shared resources for instant UI display and efficient usage.
6+
7+
## Boot process
8+
9+
1. Hyprland starts and runs `~/.config/ags/start-daemons.sh`
10+
2. Script waits for Hyprland to be ready
11+
3. Launches `ags run config-bundled.tsx`
12+
4. Components initialize in a single process
13+
5. Windows are pre-created (hidden) for instant display
14+
15+
## Startup script (`start-daemons.sh`)
16+
17+
Purpose: manage the bundled AGS process lifecycle.
18+
19+
Features:
20+
21+
- Waits for Hyprland to be ready before starting
22+
- Checks if bundled process is already running
23+
- Provides colored console output and logging
24+
- Logs to `/tmp/ags-daemons.log` for debugging
25+
26+
Usage:
27+
28+
```bash
29+
exec-once = uwsm app -- ~/.config/ags/start-daemons.sh
30+
~/.config/ags/start-daemons.sh
31+
cat /tmp/ags-daemons.log
32+
ags list
33+
```
34+
35+
Configuration (top of `start-daemons.sh`):
36+
37+
```bash
38+
WAIT_FOR_HYPRLAND=true
39+
HYPRLAND_TIMEOUT=4
40+
```
41+
42+
## Communication pattern
43+
44+
Components communicate via the `globalThis` namespace.
45+
46+
Component side (TypeScript in `lib/` files):
47+
48+
```tsx
49+
globalThis.myComponent = {
50+
show: () => myWindow.show(),
51+
hide: () => myWindow.hide(),
52+
toggle: () => myWindow.visible ? myWindow.hide() : myWindow.show(),
53+
};
54+
55+
const myWindow = (
56+
<window name="my-window" namespace="ags-myapp" visible={false}>
57+
{/* content */}
58+
</window>
59+
);
60+
```
61+
62+
Main config (`config-bundled.tsx`):
63+
64+
```tsx
65+
import "gi://Astal?version=4.0";
66+
import app from "ags/gtk4/app";
67+
68+
import "./lib/confirm-dialog.tsx";
69+
import "./lib/keyboard-switcher.tsx";
70+
import "./lib/volume-indicator.tsx";
71+
import "./lib/start-menu.tsx";
72+
import "./lib/window-switcher.tsx";
73+
74+
app.start({
75+
instanceName: "ags-bundled",
76+
requestHandler(argv: string[], res: (response: string) => void) {
77+
try {
78+
const data = JSON.parse(argv.join(" "));
79+
const component = globalThis[data.window];
80+
81+
if (component && typeof component[data.action] === "function") {
82+
component[data.action]();
83+
res("success");
84+
} else {
85+
res("unknown window or action");
86+
}
87+
} catch (e) {
88+
res(`error: ${e}`);
89+
}
90+
},
91+
});
92+
```
93+
94+
Client side (shell):
95+
96+
```bash
97+
ags request -i ags-bundled '{"window":"start-menu","action":"toggle"}'
98+
bind = $mainMod, X, exec, ags request -i ags-bundled '{"window":"start-menu","action":"toggle"}'
99+
```
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# GJS/GLib Integration
2+
3+
## Spawning commands
4+
5+
```tsx
6+
const GLib = imports.gi.GLib;
7+
8+
GLib.spawn_command_line_async("command arg1 arg2");
9+
10+
let [ok, output] = GLib.spawn_command_line_sync("command");
11+
const decoder = new TextDecoder();
12+
let result = JSON.parse(decoder.decode(output));
13+
```
14+
15+
## Keyboard events
16+
17+
```tsx
18+
const Gtk = imports.gi.Gtk;
19+
const Gdk = imports.gi.Gdk;
20+
21+
<Gtk.EventControllerKey
22+
onKeyPressed={(_, keyval) => {
23+
if (keyval === Gdk.KEY_Escape) {
24+
app.quit();
25+
return true;
26+
}
27+
return false;
28+
}}
29+
/>
30+
```
31+
32+
Common key constants:
33+
34+
- `Gdk.KEY_Escape`
35+
- `Gdk.KEY_Return`
36+
- `Gdk.KEY_Tab`
37+
- `Gdk.KEY_space`
38+
39+
## Timeouts
40+
41+
```tsx
42+
const timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1000, () => {
43+
return GLib.SOURCE_REMOVE;
44+
});
45+
46+
GLib.source_remove(timeout);
47+
```
48+
49+
## File monitoring
50+
51+
```tsx
52+
const Gio = imports.gi.Gio;
53+
54+
const file = Gio.File.new_for_path("/path/to/file");
55+
const monitor = file.monitor(Gio.FileMonitorFlags.NONE, null);
56+
monitor.connect("changed", (monitor, file, other_file, event_type) => {
57+
if (event_type === Gio.FileMonitorEvent.CHANGED) {
58+
// handle change
59+
}
60+
});
61+
```
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Hyprland Integration
2+
3+
## Layer rules
4+
5+
AGS windows need a `namespace` prop for Hyprland layer rules:
6+
7+
```tsx
8+
<window
9+
name="my-window"
10+
namespace="ags-myapp" // Used in Hyprland layerrules
11+
/>
12+
```
13+
14+
In `hyprland.conf`:
15+
16+
```
17+
layerrule = match:namespace ags-myapp, blur on
18+
layerrule = match:namespace ags-myapp, no_anim on
19+
# Don't add ignore_alpha if you want solid backgrounds.
20+
```
21+
22+
Hyprland `ignore_alpha` forces transparency. Only add it if you want the layer to be transparent.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Resources
2+
3+
- Official Docs: https://aylur.github.io/astal/guide/introduction
4+
- GTK4 CSS: https://docs.gtk.org/gtk4/css-properties.html
5+
- AGS GitHub: https://github.com/aylur/ags

0 commit comments

Comments
 (0)