blamcode 0.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- blamcode/__init__.py +9 -0
- blamcode/cli.py +122 -0
- blamcode/layer/README.md +43 -0
- blamcode/layer/config/agent/build.md +118 -0
- blamcode/layer/config/agent/debugger.md +32 -0
- blamcode/layer/config/agent/designer.md +31 -0
- blamcode/layer/config/agent/vision.md +26 -0
- blamcode/layer/config/agent/writer.md +28 -0
- blamcode/layer/config/command/ask.md +41 -0
- blamcode/layer/config/command/blam.md +24 -0
- blamcode/layer/config/command/explore.md +14 -0
- blamcode/layer/config/command/fix.md +14 -0
- blamcode/layer/config/command/open.md +18 -0
- blamcode/layer/config/command/review.md +14 -0
- blamcode/layer/config/opencode.json +53 -0
- blamcode/layer/config/themes/bangladeshi.json +67 -0
- blamcode/layer/config/themes/blamcode.json +217 -0
- blamcode/layer/config/tui.json +4 -0
- blamcode/layer/install.sh +752 -0
- blamcode/layer/scripts/__pycache__/patch-brand.cpython-312.pyc +0 -0
- blamcode/layer/scripts/blamcode +518 -0
- blamcode/layer/scripts/blamcode-browser +315 -0
- blamcode/layer/scripts/blamcode-menu +140 -0
- blamcode/layer/scripts/blamcode-uninstall +71 -0
- blamcode/layer/scripts/blamcode-vision +542 -0
- blamcode/layer/scripts/oc-settings.sh +138 -0
- blamcode/layer/scripts/patch-brand.py +267 -0
- blamcode/layer/skills/android-app/SKILL.md +53 -0
- blamcode/layer/skills/api-integration/SKILL.md +49 -0
- blamcode/layer/skills/bash-cli-expert/SKILL.md +48 -0
- blamcode/layer/skills/bot-development/SKILL.md +53 -0
- blamcode/layer/skills/clean-code-performance/SKILL.md +45 -0
- blamcode/layer/skills/database/SKILL.md +56 -0
- blamcode/layer/skills/debugging-fixes/SKILL.md +45 -0
- blamcode/layer/skills/deploy-hosting/SKILL.md +38 -0
- blamcode/layer/skills/docker/SKILL.md +74 -0
- blamcode/layer/skills/firebase-supabase/SKILL.md +61 -0
- blamcode/layer/skills/git-workflow/SKILL.md +63 -0
- blamcode/layer/skills/lets-scroll/SKILL.md +877 -0
- blamcode/layer/skills/lets-scroll/references/index-template.html +73 -0
- blamcode/layer/skills/lets-scroll/references/knockout.py +89 -0
- blamcode/layer/skills/lets-scroll/references/pipeline.md +312 -0
- blamcode/layer/skills/lets-scroll/references/prompts.md +194 -0
- blamcode/layer/skills/lets-scroll/references/scrub-engine.js +448 -0
- blamcode/layer/skills/project-structure/SKILL.md +74 -0
- blamcode/layer/skills/python-automation/SKILL.md +52 -0
- blamcode/layer/skills/react-next-best-practices/SKILL.md +54 -0
- blamcode/layer/skills/security-review/SKILL.md +48 -0
- blamcode/layer/skills/seo-basics/SKILL.md +44 -0
- blamcode/layer/skills/testing/SKILL.md +58 -0
- blamcode/layer/skills/ui-ux-responsive/SKILL.md +53 -0
- blamcode/layer/skills/website-builder/SKILL.md +47 -0
- blamcode-0.4.0.dist-info/METADATA +62 -0
- blamcode-0.4.0.dist-info/RECORD +58 -0
- blamcode-0.4.0.dist-info/WHEEL +5 -0
- blamcode-0.4.0.dist-info/entry_points.txt +2 -0
- blamcode-0.4.0.dist-info/licenses/LICENSE +21 -0
- blamcode-0.4.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""BLAMCODE brand patcher for the opencode binary.
|
|
3
|
+
|
|
4
|
+
Replaces user-visible "OpenCode" strings with "BLAMCODE" using exact byte
|
|
5
|
+
matches (same length, auto-padded with trailing spaces), so no offsets
|
|
6
|
+
are needed and missing strings are skipped per version. Functional
|
|
7
|
+
bytes (API keys, header names, protocol fields, system prompts) are
|
|
8
|
+
never touched.
|
|
9
|
+
|
|
10
|
+
Pixel-art rows use fit(): the replacement decodes to the same character
|
|
11
|
+
count (row width used by the layout code) and occupies the same byte
|
|
12
|
+
count (binary layout stays intact).
|
|
13
|
+
|
|
14
|
+
Usage:
|
|
15
|
+
patch-brand.py <input.bin> <output.bin> -- brand (OpenCode -> BLAMCODE)
|
|
16
|
+
patch-brand.py <input.bin> <output.bin> --blank-logo -- erase pixel-art
|
|
17
|
+
logo rows (all-space rows, same width/bytes, layout unchanged)
|
|
18
|
+
patch-brand.py <input.bin> <any> --verify -- exit 0 when a known logo
|
|
19
|
+
state (raw art / current design / any previously-shipped design) is
|
|
20
|
+
in the binary
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
import sys
|
|
24
|
+
|
|
25
|
+
# pixel-art wordmark rows (escaped JS strings from the home screen art)
|
|
26
|
+
# -> design rows (decoded unicode). fit() re-encodes to exact length.
|
|
27
|
+
# Each entry: (raw "OPENCODE" bytes, [every previously-shipped BLAMCODE design
|
|
28
|
+
# for this row, oldest first], current design). Any legacy state found in
|
|
29
|
+
# the binary upgrades straight to the current design in one pass, so cores
|
|
30
|
+
# branded by ANY older BLAMCODE release converge — no more half-patched mixes.
|
|
31
|
+
LOGO = [
|
|
32
|
+
(b"\\u2588\\u2580\\u2580\\u2588 \\u2588\\u2580\\u2580\\u2588 \\u2588\\u2580\\u2580\\u2588 \\u2588\\u2580\\u2580\\u2584 \\u2580\\u2580\\u2580 \\u2588\\u2580\\u2580\\u2588 \\u2588\\u2580\\u2580\\u2588 \\u2588\\u2580\\u2580\\u2588",
|
|
33
|
+
['█▀▀█ █ █ █ █ █▀▀█',
|
|
34
|
+
'█▀▀▀▀▀▀▀ █ █ █ █ █▀▀▀▀▀▀█',
|
|
35
|
+
'█▀▀▀▀▀▀█ █ █ █ █ █▀▀▀▀▀▀█',
|
|
36
|
+
'▀▀▀▀▀██▀ ▀█▄ ▄█▀ ██ ██ ▄█▀▀▀▀█▄'],
|
|
37
|
+
'█▀▀▄ █ ▄▀▀▄ █▄▄█ ▄███ ▄██▄ █▀▀▄ █▀▀'),
|
|
38
|
+
(b"\\u2588 \\u2588 \\u2588 \\u2588 \\u2588\\u2580\\u2580\\u2580 \\u2588 \\u2588 \\u2588 \\u2588 \\u2588 \\u2588 \\u2588 \\u2588\\u2580\\u2580\\u2580",
|
|
39
|
+
[' ▄▀ █▀▀█ ▀▀ █ █',
|
|
40
|
+
' ▀▀▀▀ █▀▀▀▀▀▀█ ▀ ▀ █ █',
|
|
41
|
+
' ▀▀▀▀ ▀▄ ▄▀ ▀▄ ▄▀ █ █',
|
|
42
|
+
' ▄█▀ ▀██▀ ▀▄ ▄▀ ██ ██'],
|
|
43
|
+
'█▄▄▀ █ █__█ █ █ █ █ █ █ █ █▄▄ '),
|
|
44
|
+
(b"\\u2580\\u2580\\u2580\\u2580 \\u2580\\u2580\\u2580 \\u2580\\u2580\\u2580\\u2580 \\u2580\\u2580\\u2580\\u2580 \\u2580 \\u2580 \\u2580\\u2580\\u2580\\u2580 \\u2580\\u2580\\u2580\\u2580 \\u2580\\u2580\\u2580\\u2580 \\u2580\\u2580\\u2580\\u2580",
|
|
45
|
+
['▀▀▀▀ █ ▀ ▀▀▀▀',
|
|
46
|
+
'▀▀▀▀▀▀▀▀ █ ▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀',
|
|
47
|
+
'▀▀▀▀▀▀▀▀ ██ ▀▀▀▀ ▀▀▀▀▀▀▀▀',
|
|
48
|
+
'▄▄██▄▄▄▄ ██ ▀▀ ▀█▄▄▄▄█▀'],
|
|
49
|
+
'█▄▄▀ █▄▄▄ █ █ █ █ █▄▄▄ █▄▄█ █▄▄▀ █▄▄▄'),
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
# two-tone home-screen logo: left half (dim) "OPEN" -> "ZY",
|
|
53
|
+
# right half (bright) "CODE" -> "VO" (double-wide, fills the halves).
|
|
54
|
+
# Same legacy-list structure as LOGO: any shipped generation upgrades.
|
|
55
|
+
LOGO_TN = [
|
|
56
|
+
(b"\\u2588\\u2580\\u2580\\u2588 \\u2588\\u2580\\u2580\\u2588 \\u2588\\u2580\\u2580\\u2588 \\u2588\\u2580\\u2580\\u2584",
|
|
57
|
+
['█▀▀█ █ █ █ █',
|
|
58
|
+
'█▀▀▀▀▀▀▀ █ █',
|
|
59
|
+
'█▀▀▀▀▀▀█ █ █',
|
|
60
|
+
'▀▀▀▀▀██▀ ▀█▄ ▄█▀'],
|
|
61
|
+
'█▀▀▄ █ ▄▀▀▄ █▄▄█'),
|
|
62
|
+
(b"\\u2588__\\u2588 \\u2588__\\u2588 \\u2588^^^ \\u2588__\\u2588",
|
|
63
|
+
[' ^▀ █^^█ ^▀ ',
|
|
64
|
+
' ▀▀▀▀ █^ ^█',
|
|
65
|
+
' ▀▀▀▀ ▀ ▀ ',
|
|
66
|
+
' ▄█▀ ▀██▀ '],
|
|
67
|
+
'█__ █ █__█ █ █'),
|
|
68
|
+
(b"\\u2580\\u2580\\u2580\\u2580 \\u2580\\u2580\\u2580 \\u2580\\u2580\\u2580\\u2580 \\u2580~~\\u2580",
|
|
69
|
+
['▀▀▀▀ █ ▀ ',
|
|
70
|
+
'▀▀▀▀▀▀▀▀ █ ',
|
|
71
|
+
'▀▀▀▀▀▀▀▀ ██ ',
|
|
72
|
+
'▄▄██▄▄▄▄ ██ '],
|
|
73
|
+
'█▄▄▀ █▄▄▄ █ █ █ '),
|
|
74
|
+
(b"\\u2588\\u2580\\u2580\\u2580 \\u2588\\u2580\\u2580\\u2588 \\u2588\\u2580\\u2580\\u2588 \\u2588\\u2580\\u2580\\u2588",
|
|
75
|
+
['█▀▀█',
|
|
76
|
+
'█ █ █▀▀▀▀▀▀█',
|
|
77
|
+
'██ ██ ▄█▀▀▀▀█▄'],
|
|
78
|
+
'▄███ ▄██▄ █▀▀▄ █▀▀▀'),
|
|
79
|
+
(b"\\u2588___ \\u2588__\\u2588 \\u2588__\\u2588 \\u2588^^^",
|
|
80
|
+
['█ █',
|
|
81
|
+
' ▀ ▀ █ █',
|
|
82
|
+
' ▀▄ ▄▀ █ █',
|
|
83
|
+
' ▀▄ ▄▀ █ █'],
|
|
84
|
+
'█ █ █ █ █ █__'),
|
|
85
|
+
(b"\\u2580\\u2580\\u2580\\u2580 \\u2580\\u2580\\u2580\\u2580 \\u2580\\u2580\\u2580\\u2580 \\u2580\\u2580\\u2580\\u2580",
|
|
86
|
+
['▀▀▀▀',
|
|
87
|
+
' ▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀',
|
|
88
|
+
' ▀▀▀▀ ▀▀▀▀▀▀▀▀',
|
|
89
|
+
' ▀▀ ▀█▄▄▄▄█▀'],
|
|
90
|
+
'█▄▄▄ █▄▄█ █▄▄▀ █▄▄▄'),
|
|
91
|
+
]
|
|
92
|
+
|
|
93
|
+
# (exact bytes to find, replacement "BLAMCODE" text) — replace ALL occurrences.
|
|
94
|
+
# New text is auto-padded with spaces to the old length (ASCII only).
|
|
95
|
+
PATCHES = [
|
|
96
|
+
# core screens
|
|
97
|
+
(b'setTerminalTitle("OpenCode")', b'setTerminalTitle("BLAMCODE")'),
|
|
98
|
+
(b'A(n,p,1,"OpenCode",a,void 0,O.BOLD)', b'A(n,p,1,"BLAMCODE",a,void 0,O.BOLD)'),
|
|
99
|
+
(b'agentInfo:{name:"OpenCode"', b'agentInfo:{name:"BLAMCODE"'),
|
|
100
|
+
(b'<title>OpenCode</title>', b'<title>BLAMCODE</title>'),
|
|
101
|
+
# ask / permission texts
|
|
102
|
+
(b'Tell OpenCode what to do differently',
|
|
103
|
+
b'Tell BLAMCODE what to do differently'),
|
|
104
|
+
(b'until OpenCode is restarted.', b'until BLAMCODE is restarted.'),
|
|
105
|
+
(b'will allow the following patterns until OpenCode is restarted',
|
|
106
|
+
b'will allow the following patterns until BLAMCODE is restarted'),
|
|
107
|
+
(b'This will allow the following patterns until OpenCode is restarted',
|
|
108
|
+
b'This will allow the following patterns until BLAMCODE is restarted'),
|
|
109
|
+
(b'OpenCode service failure', b'BLAMCODE service failure'),
|
|
110
|
+
(b'Request is not supported by this version of OpenCode Server (Server responded with text/html)',
|
|
111
|
+
b'Request is not supported by this version of BLAMCODE Server (Server responded with text/html)'),
|
|
112
|
+
# provider / model labels
|
|
113
|
+
(b'name:"OpenCode Zen"', b'name:"BLAMCODE Zen"'),
|
|
114
|
+
(b'name:"OpenCode Go"', b'name:"BLAMCODE Go"'),
|
|
115
|
+
(b'name:"OpenCode Default"', b'name:"BLAMCODE Default"'),
|
|
116
|
+
(b'label:"OpenCode Login"', b'label:"BLAMCODE Login"'),
|
|
117
|
+
# upgrade / connect dialogs
|
|
118
|
+
(b' and enable OpenCode Go', b' and enable BLAMCODE Go'),
|
|
119
|
+
(b'OpenCode Zen gives you access to all the best coding models at the cheapest prices with a single API key.',
|
|
120
|
+
b'BLAMCODE Zen gives you access to all the best coding models at the cheapest prices with a single API key.'),
|
|
121
|
+
(b'OpenCode Go is a $10 per month subscription that provides reliable access to popular open coding models with generous usage limits.',
|
|
122
|
+
b'BLAMCODE Go is a $10 per month subscription that provides reliable access to popular open coding models with generous usage limits.'),
|
|
123
|
+
(b'Subscribe to OpenCode Go for reliable access to the best open-source models, starting at $5/month.',
|
|
124
|
+
b'Subscribe to BLAMCODE Go for reliable access to the best open-source models, starting at $5/month.'),
|
|
125
|
+
# tips / menus
|
|
126
|
+
(b'Use {highlight}/connect{/highlight} with OpenCode Zen for curated, tested models',
|
|
127
|
+
b'Use {highlight}/connect{/highlight} with BLAMCODE Zen for curated, tested models'),
|
|
128
|
+
(b'Run {highlight}opencode serve{/highlight} for headless API access to OpenCode',
|
|
129
|
+
b'Run {highlight}opencode serve{/highlight} for headless API access to BLAMCODE'),
|
|
130
|
+
(b'Create a plugin to prevent OpenCode from reading sensitive files',
|
|
131
|
+
b'Create a plugin to prevent BLAMCODE from reading sensitive files'),
|
|
132
|
+
(b'Uninstall OpenCode', b'Uninstall BLAMCODE'),
|
|
133
|
+
(b'description:"close OpenCode"', b'description:"close BLAMCODE"'),
|
|
134
|
+
(b'Thank you for using OpenCode!', b'Thank you for using BLAMCODE!'),
|
|
135
|
+
(b'Successfully updated to OpenCode v',
|
|
136
|
+
b'Successfully updated to BLAMCODE v'),
|
|
137
|
+
# TUI session list "Continue" hint: opencode -s <id> -> blamcode -s <id>
|
|
138
|
+
(b'opencode -s ${U.sessionID}', b'blamcode -s ${U.sessionID}'),
|
|
139
|
+
]
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def fit(old: bytes, design: str) -> bytes:
|
|
143
|
+
"""Length-safe replacement for an escaped pixel-art row.
|
|
144
|
+
|
|
145
|
+
Old bytes are an escaped JS string. Returns a replacement that
|
|
146
|
+
(a) decodes to the same number of characters (row width used by the
|
|
147
|
+
layout code) and (b) occupies the same number of bytes (the rest of
|
|
148
|
+
the binary stays byte-aligned). Non-ASCII glyphs must be escaped;
|
|
149
|
+
extra escape slots are filled with escaped spaces.
|
|
150
|
+
"""
|
|
151
|
+
esc = old.count(b"\\u")
|
|
152
|
+
dec = esc + (len(old) - esc * 6)
|
|
153
|
+
g = (len(old) - dec) // 5 # #escapes if the tail is all 1-byte chars
|
|
154
|
+
l = dec - g
|
|
155
|
+
assert g * 6 + l == len(old), (len(old), dec, g, l)
|
|
156
|
+
assert len(design) <= dec, (design, dec)
|
|
157
|
+
chars = list(design) + [" "] * (dec - len(design))
|
|
158
|
+
need = [i for i, c in enumerate(chars) if ord(c) > 0x7F]
|
|
159
|
+
assert len(need) <= g, (design, g, need)
|
|
160
|
+
esc_idx = set(need)
|
|
161
|
+
for i, c in enumerate(chars):
|
|
162
|
+
if len(esc_idx) >= g:
|
|
163
|
+
break
|
|
164
|
+
if c == " " and i not in esc_idx:
|
|
165
|
+
esc_idx.add(i)
|
|
166
|
+
assert len(esc_idx) == g, (design, g, esc_idx)
|
|
167
|
+
out = "".join("\\u%04x" % ord(chars[i]) if i in esc_idx else chars[i]
|
|
168
|
+
for i in range(len(chars)))
|
|
169
|
+
out = out.encode()
|
|
170
|
+
assert len(out) == len(old), (design, len(out), len(old))
|
|
171
|
+
return out
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def load(path):
|
|
175
|
+
with open(path, "rb") as f:
|
|
176
|
+
return bytearray(f.read())
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def main():
|
|
180
|
+
if len(sys.argv) not in (3, 4) or (len(sys.argv) == 4 and sys.argv[3] not in ("--blank-logo", "--verify")):
|
|
181
|
+
print(__doc__)
|
|
182
|
+
sys.exit(1)
|
|
183
|
+
buf = load(sys.argv[1])
|
|
184
|
+
total = 0
|
|
185
|
+
if len(sys.argv) == 4 and sys.argv[3] == "--verify":
|
|
186
|
+
# exit 0 = a known logo state is present (raw OPENCODE art, the
|
|
187
|
+
# current design or ANY previously-shipped design); exit 3 = none
|
|
188
|
+
# of them (e.g. an old release blanked the art beyond repair —
|
|
189
|
+
# the caller should re-download a fresh core and re-brand).
|
|
190
|
+
for old, legacy, new in LOGO + LOGO_TN:
|
|
191
|
+
if (old in buf or fit(old, new) in buf
|
|
192
|
+
or any(fit(old, d) in buf for d in legacy)):
|
|
193
|
+
print("logo state: ok")
|
|
194
|
+
return
|
|
195
|
+
print("logo state: missing (blanked or unknown core build)")
|
|
196
|
+
sys.exit(3)
|
|
197
|
+
if len(sys.argv) == 4 and sys.argv[3] == "--blank-logo":
|
|
198
|
+
# Erase the pixel-art logo: replace every art row (as currently
|
|
199
|
+
# patched, any legacy form, or the raw unpatched form) with an
|
|
200
|
+
# all-space row of the same decoded width and byte length.
|
|
201
|
+
# Layout stays intact.
|
|
202
|
+
for old, legacy, new in LOGO + LOGO_TN:
|
|
203
|
+
for src in [old, fit(old, new)] + [fit(old, d) for d in legacy]:
|
|
204
|
+
if src not in buf:
|
|
205
|
+
continue
|
|
206
|
+
n = buf.count(src)
|
|
207
|
+
buf = buf.replace(src, fit(src, ""))
|
|
208
|
+
total += n
|
|
209
|
+
print(f"BLANK x{n} {src[:44]!r}")
|
|
210
|
+
# accent/top strips of the home + help logo (p.right / O arrays)
|
|
211
|
+
for row in (b" \\u2584 ",
|
|
212
|
+
b"\\u2800 \\u2584 "):
|
|
213
|
+
if row not in buf:
|
|
214
|
+
print(f"SKIP row {row[:30]!r}")
|
|
215
|
+
continue
|
|
216
|
+
n = buf.count(row)
|
|
217
|
+
buf = buf.replace(row, fit(row, ""))
|
|
218
|
+
total += n
|
|
219
|
+
print(f"BLANK x{n} {row[:30]!r}")
|
|
220
|
+
# 4-glyph-shape sequences (p/t left/right arrays, bright "O" etc).
|
|
221
|
+
# NOTE: do NOT touch the "_"/"^" rows of the logo font
|
|
222
|
+
# ("\\u2588__\\u2588" / "\\u2588_^\\u2588"): editing those two
|
|
223
|
+
# strings makes the standalone binary fall back to plain Bun CLI.
|
|
224
|
+
sp = b"\\u0020"
|
|
225
|
+
for g in (b"\\u2800",
|
|
226
|
+
b"\\u2588\\u2580\\u2580\\u2580",
|
|
227
|
+
b"\\u2588\\u2580\\u2580\\u2588",
|
|
228
|
+
b"\\u2580\\u2580\\u2580\\u2580"):
|
|
229
|
+
if g not in buf:
|
|
230
|
+
print(f"SKIP glyph {g!r}")
|
|
231
|
+
continue
|
|
232
|
+
n = buf.count(g)
|
|
233
|
+
buf = buf.replace(g, sp * (len(g) // 6))
|
|
234
|
+
total += n
|
|
235
|
+
print(f"BLANK-G x{n} {g!r}")
|
|
236
|
+
with open(sys.argv[2], "wb") as f:
|
|
237
|
+
f.write(buf)
|
|
238
|
+
print(f"blanked {total} logo rows -> {sys.argv[2]}")
|
|
239
|
+
return
|
|
240
|
+
for old, legacy, new in LOGO + LOGO_TN:
|
|
241
|
+
new = fit(old, new)
|
|
242
|
+
for src in [old] + [fit(old, d) for d in legacy]:
|
|
243
|
+
if src not in buf:
|
|
244
|
+
print(f"SKIP {src[:52]!r}")
|
|
245
|
+
continue
|
|
246
|
+
n = buf.count(src)
|
|
247
|
+
buf = buf.replace(src, new)
|
|
248
|
+
total += n
|
|
249
|
+
print(f"OK x{n} {src[:52]!r}")
|
|
250
|
+
for old, new in PATCHES:
|
|
251
|
+
if len(new) < len(old):
|
|
252
|
+
new = new + b" " * (len(old) - len(new))
|
|
253
|
+
assert len(old) == len(new), (old, len(old), len(new))
|
|
254
|
+
if old not in buf:
|
|
255
|
+
print(f"SKIP {old[:52]!r}")
|
|
256
|
+
continue
|
|
257
|
+
n = buf.count(old)
|
|
258
|
+
buf = buf.replace(old, new)
|
|
259
|
+
total += n
|
|
260
|
+
print(f"OK x{n} {old[:52]!r}")
|
|
261
|
+
with open(sys.argv[2], "wb") as f:
|
|
262
|
+
f.write(buf)
|
|
263
|
+
print(f"patched {total} occurrences -> {sys.argv[2]}")
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
if __name__ == "__main__":
|
|
267
|
+
main()
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: android-app
|
|
3
|
+
description: Basic Android app development from Termux — HTML/JS hybrid apps, webviews, APK building. Use when user wants to make an Android app or turn a website into an app.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Android App Skill (Termux-friendly)
|
|
7
|
+
|
|
8
|
+
## Honest path first (choose the right level)
|
|
9
|
+
- **Fastest / best on phone:** an HTML/JS "hybrid" app packaged as APK — uses the device
|
|
10
|
+
browser engine, works offline, installs like a normal app
|
|
11
|
+
- **Real native (Kotlin):** needs Android Studio — too heavy for a phone; recommend a PC
|
|
12
|
+
- **Full-power web app:** a mobile-first PWA — installable from the browser, no APK at all
|
|
13
|
+
|
|
14
|
+
## Path A — Website → APK (best for Termux users)
|
|
15
|
+
Tools that work from the phone: **PWA Builder / PWABuilder** (website) or
|
|
16
|
+
**Bubblewrap CLI** (needs Node). Simplest reliable flow:
|
|
17
|
+
1. Build the site (mobile-first, offline-friendly — see website-builder skill)
|
|
18
|
+
2. Add a web manifest (`manifest.json`: name, icons, `display: standalone`)
|
|
19
|
+
3. Add a service worker so it works offline
|
|
20
|
+
4. Package with PWABuilder (web) or `npm i -g @bubblewrap/cli` on a PC
|
|
21
|
+
5. Install the APK/AAB on the phone
|
|
22
|
+
|
|
23
|
+
PWA alone (no APK) already gives: home-screen icon, fullscreen, offline — good enough for most.
|
|
24
|
+
|
|
25
|
+
## Path B — Fully offline single-file APK (simple kiosk app)
|
|
26
|
+
```html
|
|
27
|
+
<!-- app.html — everything in one file: CSS + JS inline -->
|
|
28
|
+
<!DOCTYPE html>
|
|
29
|
+
<html>
|
|
30
|
+
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
|
|
31
|
+
<title>My App</title>
|
|
32
|
+
<style>body{font-family:sans-serif;max-width:600px;margin:auto;padding:16px}</style>
|
|
33
|
+
</head>
|
|
34
|
+
<body>
|
|
35
|
+
<h1>Hello from my phone-built app!</h1>
|
|
36
|
+
<button onclick="alert('Works offline!')">Tap me</button>
|
|
37
|
+
</body>
|
|
38
|
+
</html>
|
|
39
|
+
```
|
|
40
|
+
Serve it locally for testing: `blamcode preview` (starts a server and opens the browser).
|
|
41
|
+
|
|
42
|
+
## Rules
|
|
43
|
+
- **Test on the real phone** — emulator is not available on Termux; use `blamcode preview`
|
|
44
|
+
- Keep it **offline-first** — phone users have flaky networks
|
|
45
|
+
- **Touch targets 44px+**, font 16px+ (see ui-ux-responsive skill)
|
|
46
|
+
- Icons: provide 192px + 512px PNGs (required for manifest)
|
|
47
|
+
- Don't promise Google Play publishing — it needs a $25 account + review; side-loading (APK) is fine for personal use
|
|
48
|
+
- Never embed real API keys in the app if it will be shared — the APK can be unpacked
|
|
49
|
+
|
|
50
|
+
## Deliver
|
|
51
|
+
- The project folder + how to open/test it (`blamcode preview`)
|
|
52
|
+
- If an APK was produced: the file path + “Install from unknown sources is needed” note
|
|
53
|
+
- One line on how to publish later if the user insists (Play Console = PC + $25)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: api-integration
|
|
3
|
+
description: Work with APIs — fetch data, connect third-party services, live data for weather/payment/news sites. Use when user wants live data, API calls, or information from the internet.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# API Integration Skill
|
|
7
|
+
|
|
8
|
+
## Rules (strict)
|
|
9
|
+
- **Never hardcode API keys in code** — keep them in a `.env` file,
|
|
10
|
+
provide an `.env.example` template, and gitignore `.env`
|
|
11
|
+
- A sensitive key in frontend code is PUBLIC — everyone can see it.
|
|
12
|
+
For paid/secret keys, say it: a backend/serverless layer is needed
|
|
13
|
+
- Check free APIs first (websearch) — current status, rate limits
|
|
14
|
+
|
|
15
|
+
## Fetch pattern (vanilla JS — modern)
|
|
16
|
+
```js
|
|
17
|
+
async function loadData() {
|
|
18
|
+
try {
|
|
19
|
+
const res = await fetch('https://api.example.com/data');
|
|
20
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
21
|
+
const data = await res.json();
|
|
22
|
+
render(data);
|
|
23
|
+
} catch (err) {
|
|
24
|
+
showMsg('There was a problem loading the data — check your internet'); // user-facing
|
|
25
|
+
console.error(err); // for debugging
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
- Loading state is MANDATORY (spinner/skeleton) — a blank screen stops beginner users
|
|
30
|
+
- Human error messages — not "404" for a beginner, but "Data could not be loaded"
|
|
31
|
+
|
|
32
|
+
## CORS (common blocker)
|
|
33
|
+
- Direct browser call fails + CORS error in console → the API does not allow
|
|
34
|
+
the browser. Solutions: (1) the API's official CORS-enabled endpoint,
|
|
35
|
+
(2) your own server proxy, (3) a different API
|
|
36
|
+
- Public sites with API keys: use AllOrigins/corsproxy-type public proxies
|
|
37
|
+
(free, but NEVER with sensitive keys)
|
|
38
|
+
|
|
39
|
+
## Useful free APIs
|
|
40
|
+
- Weather: Open-Meteo (no key needed, uses lat/lon)
|
|
41
|
+
- Prayer times: Aladhan API (by city)
|
|
42
|
+
- Currency rates: exchangerate / frankfurter
|
|
43
|
+
- News/search: whatever service the user has — read its docs first
|
|
44
|
+
|
|
45
|
+
## Workflow
|
|
46
|
+
1. Read the API docs (webfetch) — endpoint, params, auth, rate limit
|
|
47
|
+
2. Small test: one call, look at the response structure
|
|
48
|
+
3. Bind data in the UI + loading + error + empty states
|
|
49
|
+
4. Respect rate limits — cache every call (localStorage with expiry)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bash-cli-expert
|
|
3
|
+
description: Safe, clean, efficient bash/CLI — Termux/Linux commands, pipes, quoting, one-liners. Use whenever running or writing any shell command or script.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Bash / CLI Expert Skill (Full-Power)
|
|
7
|
+
|
|
8
|
+
## Termux reality (it runs on the user's phone)
|
|
9
|
+
- Paths: `/storage/emulated/0/` = shared storage (FUSE — slow, case-sensitivity
|
|
10
|
+
depends on the backend), `$HOME` = fast private storage
|
|
11
|
+
- Heavy IO on shared storage is bad — copy to $HOME, work, copy back when done
|
|
12
|
+
- `pkg install <x>` = apt wrapper; `termux-open <file>` opens a file in its default app
|
|
13
|
+
- On Android 11+ the `/sdcard` symlink also works; otherwise use `/storage/emulated/0`
|
|
14
|
+
|
|
15
|
+
## Safety gates (always — the AI guards itself because of auto-approve)
|
|
16
|
+
- Read-only first: `ls`, `file`, `grep -n`, `find ... -maxdepth 2`
|
|
17
|
+
- `rm -rf` — exact absolute path, stop on empty variables (`set -u`); never target
|
|
18
|
+
`/` or `$HOME`
|
|
19
|
+
- `curl | sh` — only if the user explicitly asked
|
|
20
|
+
- `mv` will overwrite — check `[ -f dest ]` first
|
|
21
|
+
- If destructive, say what you will do first, then do it
|
|
22
|
+
|
|
23
|
+
## Command hygiene
|
|
24
|
+
- One command does one thing; chain with `&&` only when the next step depends on the previous
|
|
25
|
+
- In scripts: `set -eu` + `trap 'rm -f "$TMP"' EXIT` for temp files
|
|
26
|
+
- After `curl`/`git`/`pkg install`: check exit — `cmd || { echo fail; exit 1; }`
|
|
27
|
+
- Long tasks: `timeout 60 cmd` — hang protection
|
|
28
|
+
- JSON edits: `python3 - <<'PY'` heredoc — no fragile sed/awk regex
|
|
29
|
+
- Search: `rg` (fast, git-aware) — better than recursive grep
|
|
30
|
+
|
|
31
|
+
## Patterns (power one-liners)
|
|
32
|
+
```sh
|
|
33
|
+
# folder size ranking
|
|
34
|
+
du -sh */ | sort -h
|
|
35
|
+
# batch rename (safe preview first)
|
|
36
|
+
for f in *.JPG; do mv "$f" "${f%.JPG}.jpg"; done
|
|
37
|
+
# find + action, space-safe
|
|
38
|
+
find . -name "*.log" -print0 | xargs -0 rm
|
|
39
|
+
# quick server
|
|
40
|
+
python3 -m http.server 8080
|
|
41
|
+
# extract any format
|
|
42
|
+
tar -xf x.tar.gz / unzip -q x.zip
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Verification
|
|
46
|
+
- After changes: run again or check `$?`
|
|
47
|
+
- Config edits: `cp x x.bak` first, then `diff x.bak x`
|
|
48
|
+
- When delivering a script: test-run it once, then give the user the usage line
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bot-development
|
|
3
|
+
description: Build bots — Telegram, WhatsApp, Discord — messaging, commands, automation, buttons. Use when user wants to create a bot or automate something via chat.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Bot Development Skill
|
|
7
|
+
|
|
8
|
+
## Telegram bot (easiest — free, works great on Termux)
|
|
9
|
+
1. Talk to [@BotFather](https://t.me/BotFather) → `/newbot` → get the token
|
|
10
|
+
2. Store the token in `.env` — NEVER commit it
|
|
11
|
+
3. Python with `python-telegram-bot` (modern version 20+/21+):
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
import os
|
|
15
|
+
from dotenv import load_dotenv
|
|
16
|
+
from telegram import Update
|
|
17
|
+
from telegram.ext import Application, CommandHandler, ContextTypes
|
|
18
|
+
|
|
19
|
+
load_dotenv()
|
|
20
|
+
TOKEN = os.getenv("BOT_TOKEN")
|
|
21
|
+
|
|
22
|
+
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|
23
|
+
await update.message.reply_text("Hello! I am your bot. /help for commands.")
|
|
24
|
+
|
|
25
|
+
app = Application.builder().token(TOKEN).build()
|
|
26
|
+
app.add_handler(CommandHandler("start", start))
|
|
27
|
+
app.run_polling() # stays running — keep the phone awake
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## WhatsApp (two paths)
|
|
31
|
+
- **Beginner path:** no code — use a service (WhatsApp Business API via Meta Cloud API, or a provider like Twilio) — costs/setup involved
|
|
32
|
+
- **Automation path (advanced):** a headless browser driver (e.g. playwright) is fragile and against WhatsApp ToS — advise against it; prefer official APIs
|
|
33
|
+
- For chat widgets on websites: wa.me links work everywhere — `https://wa.me/<number>?text=...`
|
|
34
|
+
|
|
35
|
+
## Bot design rules
|
|
36
|
+
- **Start with 3 commands**: `/start`, `/help`, one real feature. That's enough
|
|
37
|
+
- Async/event-driven — never blocking loops in webhook mode
|
|
38
|
+
- **Rate limits**: Telegram allows ~30 msg/sec; add small sleeps for long broadcasts
|
|
39
|
+
- Inline keyboards (`InlineKeyboardButton`) beat typing for choices — mobile-friendly
|
|
40
|
+
- Long tasks: reply "processing…" first, then edit the message when done
|
|
41
|
+
- Log errors to a file; add a `/admin` (owner-only) status command
|
|
42
|
+
|
|
43
|
+
## Running 24/7 on Termux
|
|
44
|
+
- `termux-wake-lock` prevents the CPU from sleeping
|
|
45
|
+
- `pkg install termux-services` + `sv-enable` keeps it alive across app restarts
|
|
46
|
+
- For real 24/7: a free bot host (Railway/Render free tiers) or user's own VPS
|
|
47
|
+
- Simple alternative: a `while True` + `time.sleep` loop with `python3 bot.py` in tmux
|
|
48
|
+
|
|
49
|
+
## Security
|
|
50
|
+
- Token in `.env`, gitignored
|
|
51
|
+
- Never log incoming messages that contain secrets
|
|
52
|
+
- Validate/escape user input before storing or echoing
|
|
53
|
+
- Webhook URL: use a secret path (`/webhook/<token>`) — public bots get scanned instantly
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: clean-code-performance
|
|
3
|
+
description: Make code clean, readable, maintainable + fast. Use when writing or refactoring any code in any language.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Clean Code + Performance Skill (Full-Power)
|
|
7
|
+
|
|
8
|
+
## Clean code — non-negotiable
|
|
9
|
+
- Names say what they do: `fetchUserData()` good, `proc2()` bad
|
|
10
|
+
- One function does one thing; split it when it passes 30-40 lines
|
|
11
|
+
- DRY — if you copy-paste a third time, make a function
|
|
12
|
+
- Nesting beyond 3 levels = add early returns
|
|
13
|
+
- Comments: write WHY, not WHAT (the code already shows what)
|
|
14
|
+
- Before delivering: remove unused code, console.log/debug prints, dead flags
|
|
15
|
+
- Consistent style: follow the existing code — not your own preference
|
|
16
|
+
|
|
17
|
+
## Error handling — critical for beginner users
|
|
18
|
+
- Every external operation (fetch, file, db) = try/catch + user-facing message
|
|
19
|
+
- Not just "Something went wrong" — what broke + what to do about it
|
|
20
|
+
- Handle empty states: no crash when data is missing, friendly message instead
|
|
21
|
+
- Technical errors in console (debug), human messages on screen
|
|
22
|
+
|
|
23
|
+
## Performance — for phone users (in real impact order)
|
|
24
|
+
1. **Network**: loading state on every request; debounce search input (300ms);
|
|
25
|
+
cache (memory/localStorage + expiry); parallel where possible (`Promise.all`)
|
|
26
|
+
2. **Bundle**: no framework for small sites (vanilla is enough); code-split big apps;
|
|
27
|
+
remove unused dependencies
|
|
28
|
+
3. **Render**: `key` on list items; memo only on measured slow components; event
|
|
29
|
+
delegation on dynamic lists
|
|
30
|
+
4. **Media**: `loading="lazy"`, set width/height, webp; hero image eager instead of lazy
|
|
31
|
+
5. **Compute**: no DOM read/write mix inside loops (batch it);
|
|
32
|
+
for large data use a map instead of O(n²) nested loops
|
|
33
|
+
|
|
34
|
+
## Refactor method
|
|
35
|
+
1. Test/run first and note the current behavior
|
|
36
|
+
2. Refactor in small steps (rename → extract function → move) — one at a time
|
|
37
|
+
3. Run again after every step — breaks get caught immediately
|
|
38
|
+
4. Never combine behavior changes with refactoring
|
|
39
|
+
|
|
40
|
+
## Checklist (before delivering)
|
|
41
|
+
- [ ] All function names self-explanatory
|
|
42
|
+
- [ ] Error + empty + loading states present
|
|
43
|
+
- [ ] Unused code/prints removed
|
|
44
|
+
- [ ] No obvious perf issues (N+1, heavy work on every render)
|
|
45
|
+
- [ ] Ran/tested at least once
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: database
|
|
3
|
+
description: Work with databases — SQLite, MySQL, PostgreSQL — design, query, connect from apps, CRUD. Use when user wants to store data, build a database, or connect an app to a database.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Database Skill
|
|
7
|
+
|
|
8
|
+
## Choose the right one (based on the user's scenario)
|
|
9
|
+
- **SQLite** — best for Termux/phone apps and small projects (single file, zero setup)
|
|
10
|
+
- **MySQL** — classic web backend (shared hosting, PHP, Laravel)
|
|
11
|
+
- **PostgreSQL** — modern, powerful, best for real production apps
|
|
12
|
+
- No database server needed for simple scripts? Use JSON files or SQLite — keep it light
|
|
13
|
+
|
|
14
|
+
## SQLite (Termux-friendly — recommended for phone projects)
|
|
15
|
+
```sh
|
|
16
|
+
pkg install sqlite
|
|
17
|
+
sqlite3 app.db # open the database interactively
|
|
18
|
+
```
|
|
19
|
+
```sql
|
|
20
|
+
-- create + insert + query
|
|
21
|
+
CREATE TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, email TEXT UNIQUE);
|
|
22
|
+
INSERT INTO users (name, email) VALUES ('Rahim', 'rahim@example.com');
|
|
23
|
+
SELECT * FROM users WHERE name LIKE 'Ra%';
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Connecting from Python (stdlib — no pip needed for SQLite)
|
|
27
|
+
```python
|
|
28
|
+
import sqlite3
|
|
29
|
+
conn = sqlite3.connect("app.db") # file is created if missing
|
|
30
|
+
conn.execute("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)")
|
|
31
|
+
conn.execute("INSERT INTO users (name) VALUES (?)", ("Karim",)) # NEVER f-strings
|
|
32
|
+
conn.commit()
|
|
33
|
+
for row in conn.execute("SELECT * FROM users"):
|
|
34
|
+
print(row)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Rules (strict)
|
|
38
|
+
- **Parameterized queries ALWAYS** — `?` placeholders (SQLite) or `%s` (MySQL/PG).
|
|
39
|
+
Never build SQL by string concatenation — that is SQL injection
|
|
40
|
+
- **Backup before destructive changes**: `sqlite3 app.db ".backup app.db.bak"` or `mysqldump`
|
|
41
|
+
- **Indexes** on columns used in WHERE/JOIN once data grows
|
|
42
|
+
- **Transactions** for multi-step writes: `BEGIN` ... `COMMIT` / `ROLLBACK`
|
|
43
|
+
- Keep the DB file OUT of git — `.gitignore` it; seed data via a `schema.sql` + `seed.py`
|
|
44
|
+
- MySQL/PG passwords: `.env` file, never hardcoded
|
|
45
|
+
|
|
46
|
+
## Schema design (quick path)
|
|
47
|
+
1. Start with a simple table + the ONE main query you need
|
|
48
|
+
2. Normalize only when you see real duplication (don't over-engineer)
|
|
49
|
+
3. Add `created_at` timestamps — always useful later
|
|
50
|
+
4. Foreign keys ON — prevents orphan rows
|
|
51
|
+
|
|
52
|
+
## Common Termux scene
|
|
53
|
+
- User wants a data-collection app (inventory, attendance, notes) → SQLite + Python
|
|
54
|
+
- Web app needs storage → MySQL (shared hosting) or SQLite (small/single-user)
|
|
55
|
+
- User has an "app.db" that won't open → check it is a real SQLite file:
|
|
56
|
+
`file app.db` and `sqlite3 app.db ".tables"`
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: debugging-fixes
|
|
3
|
+
description: Systematic debugging — fix errors, solve crashes, find why something is not working. Use when user reports any problem, error, crash, or unexpected behavior.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Debugging Skill (Full-Power)
|
|
7
|
+
|
|
8
|
+
## Golden rule
|
|
9
|
+
Read the ENTIRE error message. The real cause is usually in the last 3-5 lines of the error.
|
|
10
|
+
Reading it for 10 seconds beats guessing a fix.
|
|
11
|
+
|
|
12
|
+
## Systematic method (in order — no skipping)
|
|
13
|
+
1. **REPRODUCE** — check whether the error happens again (run it)
|
|
14
|
+
2. **READ** — read the whole error + stack trace. Which file, which line? Mark `file:line`
|
|
15
|
+
3. **ISOLATE** — make a small test case or read the related file (read tool).
|
|
16
|
+
Do not touch anything until you have narrowed down the problem zone
|
|
17
|
+
4. **ROOT CAUSE** — fix the cause, not the symptom. "Deleting this makes the error go
|
|
18
|
+
away" means the deletion is hiding the problem, not fixing it
|
|
19
|
+
5. **FIX** — small, targeted change. No full-file rewrites. Surgical edit,
|
|
20
|
+
`cp x x.bak` backup first if it feels risky
|
|
21
|
+
6. **VERIFY** — run again. If it works, regression check: make sure previously
|
|
22
|
+
working features did not break
|
|
23
|
+
7. **EXPLAIN** — tell the user in 2-3 lines: what was broken, what was fixed,
|
|
24
|
+
and the exact command if a restart/reinstall is needed
|
|
25
|
+
|
|
26
|
+
## Tool tricks
|
|
27
|
+
- `sh -n script.sh` — shell syntax check, `node --check f.js`, `python3 -m py_compile f.py`
|
|
28
|
+
- No logs? Add `console.log` / `print` to isolate — remove them after the fix
|
|
29
|
+
- Web: ask the user to copy the browser console errors
|
|
30
|
+
- Dependency errors: version mismatch is common — check `npm ls`, the lock file, changelogs
|
|
31
|
+
|
|
32
|
+
## Common quick wins
|
|
33
|
+
- `command not found` → package missing / not on PATH
|
|
34
|
+
- Node `ERR_MODULE_NOT_FOUND` → missing `.js` extension on relative import / wrong path
|
|
35
|
+
- Python `ModuleNotFoundError` → `pip install <mod>`
|
|
36
|
+
- Blank/not working website → file paths are **case-sensitive** (Linux!), hard-refresh the cache
|
|
37
|
+
- Port in use → different port or `kill $(lsof -t -i:PORT)`
|
|
38
|
+
- CORS error → the API side needs CORS, or use a same-origin proxy
|
|
39
|
+
- Termux build tool fails → glibc dependency — use proot Ubuntu or an alternative package
|
|
40
|
+
|
|
41
|
+
## If stuck (after 2 attempts)
|
|
42
|
+
- Websearch the exact error string
|
|
43
|
+
- Check version migration notes — APIs change between upgrades
|
|
44
|
+
- Step back: make it smaller — start from a minimum working example and add features gradually
|
|
45
|
+
- Ask the user 3 things: what they were trying to do / what they expected / what actually happens
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: deploy-hosting
|
|
3
|
+
description: Put a website live — free hosting (GitHub Pages, Netlify, Vercel), domains, deploys. Use when user says "make it live", "deploy", "go online", "upload the website", or wants a public link.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Deploy & Hosting Skill
|
|
7
|
+
|
|
8
|
+
## Choose a path (based on the user's scenario)
|
|
9
|
+
|
|
10
|
+
### 1. Netlify Drop (EASIEST — for static sites, no account needed)
|
|
11
|
+
- Drag-and-drop the site folder at https://app.netlify.com/drop
|
|
12
|
+
- Instant live link (.netlify.app)
|
|
13
|
+
- Works on a phone too — straight from the browser
|
|
14
|
+
- Tell the user: zip the folder and drop it, or select the files
|
|
15
|
+
|
|
16
|
+
### 2. GitHub Pages (free, permanent, if you know git)
|
|
17
|
+
- Create a repo → push the site files → Settings → Pages → select branch
|
|
18
|
+
- Link: `username.github.io/repo-name`
|
|
19
|
+
- On Termux: `git init`, push — see the git-workflow skill in blamcode
|
|
20
|
+
- If 404: use relative paths (`./style.css`, `/repo-name/` base tag)
|
|
21
|
+
|
|
22
|
+
### 3. Vercel (best for React/Next.js apps)
|
|
23
|
+
- `npm i -g vercel` → run `vercel` → link account → deploy
|
|
24
|
+
- Preview + production automatic — every push updates it
|
|
25
|
+
|
|
26
|
+
### 4. Direct from Termux (local test)
|
|
27
|
+
- `python3 -m http.server 8080` → open `localhost:8080` in the phone's browser
|
|
28
|
+
|
|
29
|
+
## Rules
|
|
30
|
+
- Verify BEFORE deploying: index.html at the root, relative paths, all assets local
|
|
31
|
+
- Never push the user's personal keys/tokens to a repo or public site
|
|
32
|
+
- On a free subdomain, say: a custom domain costs money but is not required
|
|
33
|
+
- Custom domain wanted: .com ~BDT 1,000-1,500/year (Namecheap/Cloudflare), help with DNS setup
|
|
34
|
+
|
|
35
|
+
## Deliver format
|
|
36
|
+
- Give the live link
|
|
37
|
+
- Say it can be shared — it works for everyone
|
|
38
|
+
- One line on how to update (drop again / git push / vercel)
|