Communitygithub.com

2016judea/ascii-charts

유니코드 블록 문자로 막대, 범위, 불릿, 갭 브래킷, 별 히스토그램, 히트맵, 꺾은선, 벤, 원형, 도넛, 산점도 차트를 만듭니다. 의존성 없는 파이썬 스크립트로, 고정폭 텍스트만 존재하는 환경(뉴스레터 코드 블록, 마크다운, 터미널, 일반 텍스트 이메일, 채팅)에 적합합니다. 이미지나 타사 차트 서비스 대신 문자 그대로 삽입해야 할 때, 또는 브랜딩 푸터 없이 손수 만든 터미널 느낌을 원할 때 사용하세요.

ascii-charts란 무엇인가요?

이 스킬은 순수 유니코드 블록 문자(예: █▓▒░)를 사용하여 터미널 스타일 차트를 생성하는 의존성 없는 파이썬 스크립트(`scripts/ascii_chart.py`)를 제공합니다. 막대, 범위 막대, 불릿, 갭 브래킷, 별 히스토그램, 히트맵, 꺾은선, 스파크라인, 벤 다이어그램, 원형, 도넛, 산점도 등 13가지 차트 유형을 지원하며, 각 유형별로 전용 함수가 있습니다. 이 차트들은 마크다운 코드 블록, HTML `<pre>` 태그, 터미널 등 고정폭 글꼴이 렌더링되는 곳 어디에서나 동일하게 표시됩니다. 색상이나 이미지가 아닌 문자만으로 데이터를 시각화하므로, 타사 서비스나 푸터 없이 문자 그대로 삽입해야 하는 뉴스레터, 채팅, 이메일 등에 이상적입니다. 또한 사용자에게 2초 테스트(차트를 보자마자 이해할 수 있는지)를 적용하도록 권장하며, 데이터를 불필요하게 차트로 만들지 말고 명확한 문장으로 전달할 수 있다면 차트를 생략하라고 조언합니다. Claude Code, Cursor 등 모든 AI 에이전트에서 사용할 수 있습니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/2016judea/brick-mortar-skills/tree/HEAD/skills/ascii-charts

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

ASCII 차트

유니코드 블록 문자로 만들어진 터미널 스타일 차트를 문자 그대로 텍스트로 삽입합니다: 마크다운의 펜스 코드 블록, HTML의 <pre> 태그 등. 차트 서비스, "제작" 푸터, 외부 계정이 필요 없으며, 고정폭 글꼴이 렌더링되는 모든 곳에서 동일하게 표시됩니다.

scripts/ascii_chart.py에는 차트 유형별로 하나의 함수가 있습니다. python3 scripts/ascii_chart.py를 실행하면 모든 유형의 예제를 각각 한 개씩 출력하여 정상 동작을 확인할 수 있습니다.

여기서 두 가지는 측정된 값이며, 처음에는 모두 틀렸습니다: 390px 휴대폰 뷰포트에서 ~44자를 넘는 행은 오른쪽 가장자리가 잘리고, 고정폭 글꼴에서 "원형"을 그리려면 약 2.49(2.0이 아님)의 수평 종횡비 보정이 필요합니다. 크기 조정 및 원형/도넛 섹션을 참조하세요.

뉴스레터 플랫폼마다 코드 블록을 붙여넣는 방식이 다릅니다. 하나에 의존하기 전에 테스트 차트를 실제 초안에 붙여넣고 웹, 앱, 이메일 렌더링을 확인하세요.

문자 집합

  • █ ▓ ▒ ░ (U+2588, U+2593, U+2592, U+2591 — 전체/진함/중간/연함 음영) — 채우기 밀도, "가장 많음"에서 "가장 적음"까지. 막대는 █/░만 사용 (채워짐 vs. 트랙); 원형/도넛은 네 가지를 모두 사용 (슬라이스가 4개를 초과하면 ▚/▞/▤/▥ 추가)하여 슬라이스별로 구분되는 채우기 패턴을 제공합니다; 히트맵은 네 가지에 더해 가장 낮은 수준을 위해 ·(가운데 점, 빈칸 아님)을 사용하므로 "조용한" 셀도 의도적인 그리드의 일부로 읽히고 빈 공간으로 보이지 않습니다.
  • 숫자 1–7 — 벤 영역 코드 (영역이 속한 집합의 비트마스크 — 아래 벤 섹션 참조)
  • + — 표시된 최대값보다 더 높을 수 있는 범위 막대의 개방형 플래그 (가지고 있지 않은 숫자를 속이기 위해 막대 자체를 늘리지 마세요)
  • ┃ — 불릿 차트 대상 눈금, 아래의 채우기/음영 위에 그려져 항상 표시됩니다.
  • └─┘ — 갭 브래킷, 두 막대 끝 사이를 연결합니다.
  • ★/☆ — 채워진/빈 별, 별 히스토그램의 행 레이블로도 사용됩니다.
  • 상자 그리기 (─│╭╮╰╯) — 꺾은선 차트 및 추세선 연결선
  • ● — 산점도 점 마커

어디에도 색상은 없습니다. 그것은 매체의 특성일 뿐, 우회해야 할 제한이 아닙니다 — 붙여넣은 Substack 코드 블록은 문자 그대로의 문자이며 다른 것은 남지 않습니다 (인라인 CSS, 스타일이 지정된 범위 없음). 차트가 필요한 모든 구분은 문자/숫자/범례에 있으며, 사용할 수 없는 색상 채널에 있지 않습니다.

차트 유형 메뉴

작업함수사용처
여러 범주, 모두 0에서 시작하는 크기 비교bar(value, max_value, width) + render()주유 (5분) vs. DC 급속 충전 (45분)
최소-최대 범위, 한 범주range_bar(start, end, scale_max, width, open_ended=) + render()"$100k–$300k+ 설치"
두 값, 전후 비교일반 텍스트: f"{start} → {end}""도매 $220 → 탭룸 $650" — 막대는 아무것도 더하지 않습니다; 화살표 자체가 차트입니다
하나의 측정값 vs. 벤치마크 대역 + 목표bullet(value, scale_max, target=, benchmark=) + render()"귀하의 평점: 4.2, 정상 범위 3.8–4.5, 목표 4.7"
두 막대 사이의 간격을 명시적으로 표시gap_bracket(a, b, scale_max, width, label=) via render(bracket=)"귀하 vs. 시장 중앙값" — 보고서의 특징적인 요소
1–5 (또는 유사) 평점 분포star_histogram(counts)Google/Yelp 별점 분석, 별 개수당 한 행
두 범주형 축, 강도별 음영heatmap(matrix, row_labels, col_ticks=)요일 × 시간별 방문자 수 — "언제 바쁘고/한가한지"
시간에 따른 추세, 하나의 시리즈line_chart(values, height, x_labels=)월별 수익, 1년간 리뷰 수
문장 내 인라인 추세sparkline(values)"월별 리뷰: ▂▃▅▆█▇▅▃, 3월 이후 3배 증가"
2~3개의 명명된 집합, 겹침의 정도 자체가 발견venn(labels)"한 별점 리뷰의 38%가 대기 시간도 언급합니다" — 겹침 크기가 핵심
전체의 부분, 한 스냅샷pie(slices, radius)수익 구성: 커피 / 따뜻한 음식 / 음료 / 복권
전체의 부분, 헤드라인 총계 포함donut(slices, radius, center_text=)위와 동일, 빈 중앙에 "247개 리뷰" 표시
두 숫자 변수, 관계가 있는지scatter(points, width, height)경쟁사 간 가격 vs. 평점
위와 동일, "그리고 여기에 추세선이 있습니다"scatter_with_trend(points, width, height)위와 동일, 상관관계를 증명하는 피팅 라인 포함

이 표에 맞는 것이 없으면, 맞지 않는 형태를 강제하기보다 멈추고 생각하세요 — 기술적으로 렌더링 가능하지만 혼란스러운 차트는 Chrome headless PNG 파이프라인으로 대체하는 것보다 더 나쁩니다.

차트를 위한 2초 테스트

좋은 문장과 마찬가지로 차트도 동일한 기준을 충족해야 합니다: 피곤한 독자가 휴대폰에서 첫눈에, 다시 읽거나 디코딩하지 않고 이해할 수 있어야 합니다. 차트 유형을 선택하기 전에 테스트를 적용하세요, 차트를 만든 후가 아니라.

2초 테스트: 의도된 독자 — 데이터 분석가가 아닌 소규모 사업주 — 가 범례를 먼저 읽지 않고 2초 이내에 이 차트가 무엇을 의미하는지 말할 수 있습니까? 하나의 영역이나 슬라이스를 이해하기 위해 먼저 범례를 디코딩해야 한다면, 그것은 전문 용어의 시각적 등가물입니다: 기술적으로 정확하지만 독자로 하여금 작업을 하게 만들고 앞으로 끌어당기지 않습니다.

실제 이슈에서 적발됨, 편집자가 렌더링된 포스트를 처음 읽을 때:

  • 3-집합 벤 숫자-비트마스크 다이어그램은 어떤 영역이 의미하는지 이해하기 전에 7줄 범례를 읽어야 했습니다. 편집자: 이해하지 못했으므로 일반 사업주도 이해하지 못할 것입니다. 기본 사실 — "이 세 가지가 모두 필요하고 하나만으로는 안 된다" — 는 한 문장이며, 다이어그램 바로 다음의 번호 목록이 이미 일반 영어로 말하고 있었습니다. 다이어그램은 산문이 이미 더 명확하게 전달한 정보에 추가하지 않으면서 디코딩 비용을 추가했습니다. 수정: 잘라내고, 문장 + 목록이 작업을 수행하도록 하세요.
  • DC 급속 충전기 비용 범위 막대 (축도, 비교 지점도 없는 단일 막대)는 비교할 대상이 없었습니다. 막대의 가치는 무언가에 상대적인 크기를 보여주는 데서 옵니다 — 척도, 다른 막대, 벤치마크. 참조 지점이 없는 단일 막대는 장식적일 뿐 정보를 제공하지 않습니다. 그것이 설명한 숫자($100k–$300k+)는 한 문장 앞서 이미 명확히 설명되어 있었습니다. 수정: 그것도 잘라내세요.

따르는 규칙:

  • 읽기 위해 자체 범례가 필요한 차트는 경고 신호입니다 — 벤에만 해당하는 것이 아닙니다. 레이블이 없는 축이 있는 히트맵, 또는 독자가 머릿속에 담을 수 있는 것보다 더 많은 슬라이스가 있는 원형 차트도 같은 방식으로 실패합니다.
  • 일반 문장이 차트만큼 명확하게 사실을 진술한다면 차트를 건너뛰세요. 산문에서 "여러/많은/다양한"을 실제 숫자로 바꾸는 것과 동일한 본능입니다: 비교 또는 추세가 핵심이기 때문에 시각적 요소를 사용하고, 데이터에 형태가 있다는 이유만으로 사용하지 마세요.
  • 모든 막대에는 축(render(..., axis=)) 또는 비교할 동일한 척도의 두 번째 막대가 필요합니다. 둘 다 없는 단일 막대는 아무것도 전달하지 않습니다 — 실제 주어가 없는 수동태 문장과 동일한 실패입니다. 그러나 이것이 충족되면, 축이 각 행의 값 레이블에 이미 있는 숫자를 반복할 뿐이라면 축을 제거하세요 — 하나의 가스-대-충전 막대는 정확히 이 이유로 0 ... 45 min 축 라인을 제거했습니다: 두 행 모두 이미 자체 값("5 min", "45 min")을 가지고 있으므로 축은 "45 min"을 두 번째로 반복했을 뿐입니다. 문장에서 중복 절을 자르는 것과 동일한 원칙입니다.
  • 이미 하나의 명확한 문장인 숫자는 차트로 만들지 마세요. "$100k–$300k+ 설치"는 텍스트로 최대한 명확합니다; 차트로 만드는 것은 비교, 추세, 또는 겹침을 드러내지 않고 보상 없는 디코딩 단계를 추가할 뿐입니다.
  • 완성된 차트를 처음부터 읽어보세요, 실제 독자가 읽을 방식으로 — 방금 차트를 만들고 그것이 무엇을 말해야 하는지 이미 아는 사람이 아니라 휴대폰을 보는 주유소 주인처럼.

작업 흐름

문자를 수동으로 정렬하거나 기하학을 직접 래스터화하는 대신 scripts/ascii_chart.py를 사용하세요 — 열 계산과 원/각도 계산은 눈으로 미묘하게 잘못되기 쉽고 나중에야 한 문자 오정렬이나 비대칭 원으로 드러나는 종류의 작업입니다. python3 scripts/ascii_chart.py를 언제든지 실행하여 모든 차트 유형의 예제를 하나씩 출력하고 정상 동작을 확인하세요.

막대 / 범위 막대

from ascii_chart import bar, range_bar, render

rows = [
    ("주유", bar(5, 45, 24), "5분"),
    ("DC 급속 충전", bar(45, 45, 24), "45분"),
]
print(render(rows, axis=("0", "45분")))

row = ("DC 급속 충전기", range_bar(100, 300, 300, 24, open_ended=True), "$100k–$300k+")
print(render([row]))

render()는 (label, bar_string, value_str) 튜플을 받아 모든 열 정렬을 처리합니다 — 자체 사전 형식의 value_str(통화, 단위 등)을 전달하세요; 함수는 기하학만 처리합니다.

불릿 차트

from ascii_chart import bullet, render

rows = [("평균 평점", bullet(4.2, 5.0, target=4.7, benchmark=(3.8, 4.5), width=24), "4.2 (목표 4.7)")]
print(render(rows, axis=("0", "5.0")))

측정된 value에 대한 실선 막대, 선택적 음영 benchmark 대역("정상" 범위, ▒) 위에 그려지며 선택적 target 눈금(┃, 항상 마지막에 그려져 아래의 모든 채우기/음영 위에 보입니다)이 있습니다. 한눈에 "내가 정상 범위 안에 있는지, 목표에서 얼마나 떨어져 있는지"에 답합니다 — 여전히 하나의 실제 막대(측정값)만 있습니다; 대역은 맥락입니다.

갭 브래킷

from ascii_chart import bar, gap_bracket, render

rows = [("귀하", bar(42000, 60000, 24), "$42,000"), ("시장 중앙값", bar(58000, 60000, 24), "$58,000")]
print(render(rows, bracket=gap_bracket(42000, 58000, 60000, 24)))

두 막대 끝 사이를 연결하는 └─┘ 브래킷, 가운데에 간격의 크기가 표시됩니다 (두 값에서 자동 서식 지정, 또는 label=에 자체 텍스트 전달). 막대와 브래킷에 동일한 scale_max/width를 사용하세요, 그렇지 않으면 범위가 맞지 않습니다. 이것은 "귀하 vs. 시장"을 독자가 눈으로 가늠하도록 두지 않고 명시적으로 만듭니다.

별 히스토그램

from ascii_chart import star_histogram

print(star_histogram([(5, 61), (4, 22), (3, 9), (2, 4), (1, 4)]))

counts는 원하는 순서로 인쇄된 [(stars, count), ...]입니다 (보통 5부터 1까지 내림차순). 채워진/빈 별 글리프(★/☆)는 행 레이블 역할을 합니다 — 텍스트로 "별 5개"를 다시 쓸 필요가 없습니다. 전적으로 bar() + render()를 기반으로 구축되었습니다.

히트맵

from ascii_chart import heatmap

print(heatmap(matrix, ["월", "화", "수", "목", "금", "토", "일"],
              col_ticks=[(0, "오전12시"), (6, "오전6시"), (12, "오후12시"), (18, "오후6시")]))

matrix는 행 × 열의 숫자 강도(예: 7일 × 24시간)이며, 행 전체가 아닌 전체 행렬에 걸쳐 정규화되므로 음영이 행 간에 비교 가능합니다. col_ticks는 [(column_index, label), ...]입니다 — 자동 간격 없음, 전달하는 레이블에 대해 충돌하지 않는 위치를 선택하세요.

꺾은선 차트 / 스파크라인

from ascii_chart import line_chart, sparkline

print(line_chart([120, 135, 128, 150, 175, 190, 205, 198, 220],
                  height=10, x_labels=("1월", "9월")))

print(sparkline([3, 5, 4, 8, 12, 10, 15, 14, 18]))

line_chart는 상자 그리기 모서리(╭╮╰╯│─)로 연결된 선을 그립니다 — 임의의 중간 기울기에 대한 문자가 없으므로 너비는 len(values) - 1 열 (세그먼트당 하나)로 고정됩니다. x_labels는 제공된 경우 축 행에 인쇄된 (first, last)일 뿐입니다 — 중간 지점은 주변 산문에서 말하고, 모든 눈금에 레이블을 지정하려고 하지 마세요. sparkline은 단일 행 8단계 추세(▁▂▃▄▅▆▇█)로, 독립형 차트가 아닌 문장 내 한 절에 사용됩니다.

벤 다이어그램 (2개 또는 3개 집합)

from ascii_chart import venn

diagram, legend = venn(["고속도로 출구", "큰 상점", "그리드 용량"])
print(diagram)
print(legend)

겹치는 원을 래스터화하고 각 영역을 숫자(해당 영역이 속한 집합의 비트마스크: 단일 집합의 경우 1, 2, 4, 쌍별 겹침의 경우 3/5/6, 세 집합 모두의 경우 7)로 채웁니다. 곡선 경계 내에 레이블 텍스트를 맞추려고 시도하는 대신, 이는 고정폭 렌더링에서 작동하지 않습니다. 범례(별도로 반환, 둘 다 출력)는 각 숫자를 실제 레이블 조합에 매핑합니다(예: 7 = 고속도로 출구 + 큰 상점 + 그리드 용량 <- 모두). 이것은 원래 ASCII에서 불가능하다고 믿어졌습니다 (초기 게시물은 벤 다이어그램에 대해 headless-Chrome PNG에 의존했습니다) — 숫자-영역 기술이 이를 깔끔하게 해결합니다; 벤 다이어그램이 PNG 폴백을 필요로 하는 경우는 더 이상 없습니다.

그러나 사용하기 전에 위의 2초 테스트를 적용하세요 — 숫자 범례 자체가 실제 사례에서 일반 독자에게 벤 다이어그램을 혼란스럽게 만든 원인이었습니다. 벤 다이어그램은 겹침의 정도가 발견일 때 제 역할을 합니다 (예: "한 별점 리뷰의 38%가 대기 시간도 언급합니다"). 실제 메시지가 "세 가지가 모두 함께 필요하고 부분 점수는 안 된다"일 때는, 올바르게 렌더링되더라도 벤 다이어그램은 잘못된 도구입니다 — 일반 텍스트가 범례 없이 그 작업을 수행합니다, 예:

고속도로 출구  +  큰 상점  +  그리드 용량
        이 중 하나라도 놓치면 사이트를 건너뛰세요

원형 차트 / 도넛 차트

from ascii_chart import pie, donut

diagram, legend = pie([("커피", 40), ("따뜻한 음식", 25), ("음료", 20), ("복권", 15)], radius=9)
print(diagram); print(legend)

diagram, legend = donut([("커피", 40), ("따뜻한 음식", 25), ("음료", 20), ("복권", 15)],
                         radius=9, center_text="247")
print(diagram); print(legend)

슬라이스는 12시 방향에서 시작하여 시계 방향으로 진행됩니다(표준 원형 차트 규칙). 각각은 고유한 채우기 문자(█▓▒░▚▞▤▥, 일반적인 2~6개 슬라이스 수에서 인접 슬라이스와 반복되지 않음)를 가지므로 색상 없이도 경계를 읽을 수 있습니다. donut은 가운데가 빈 pie입니다 — center_text는 헤드라인 숫자/레이블(예: 총 개수)을 그곳에 배치하며, 이것이 ASCII 도넛이 실제 도넛이 보통 빈 공간에 낭비하는 한 가지를 할 수 있는 유일한 것입니다. radius는 행 단위입니다; 함수는 내부적으로 고정폭 문자 종횡비 (공유 ASPECT 상수, venn()에서도 사용됨)를 보정하므로 결과는 실제로 평평한 타원이 아닌 원형입니다 — 너비/높이를 별도로 수동 조정하지 말고 radius만 전달하세요.

수정: ASPECT는 처음에 가정된 2.0으로 하드코딩되었으며 한 번도 조정되지 않았습니다. 이제 올바르게 측정된 2.49가 사용됩니다.

Sizing

render(..., width=)에 의해 처리되는 가로 너비: 모든 차트 구성 요소(레이블, 막대, 값 열)를 포함하는 행당 총 문자 수입니다. 390px 휴대폰 뷰포트에서 렌더링을 확인하세요.

세로 높이는 차트 유형에 따라 다릅니다:

  • 막대/범위 막대/불릿: 행 수 = len(rows) (고정)
  • 꺾은선 차트: height=로 설정, 값 수에 따라 자동 조정
  • 원형/도넛/산점도: radius=로 설정, 차트 유형에 따라 해석

히트맵과 별 히스토그램은 데이터에서 자체 크기를 결정합니다.

차트 유형 선택

위의 메뉴와 2초 테스트를 안내로 사용하세요. 메시지에 맞지 않는 차트 유형을 강제하지 마세요 — 일반 텍스트가 작업을 명확하게 수행한다면 사용하세요.

추가 참고 사항

  • 의존성이 없습니다: scripts/ascii_chart.py는 표준 라이브러리만 사용합니다.
  • 차트는 완전히 결정론적입니다: 동일한 입력은 항상 동일한 출력을 생성합니다.
  • 모든 차트 유형은 깊게 중첩된 구조 없이 단일 함수 호출로 생성됩니다.
  • 오류 처리는 최소화되어 있습니다: 유효한 입력을 가정합니다.

Individual skills in this repo

This repo contains 7 individual skills — each has its own dedicated page.

2016judea/buffett-checklist

Apply Warren Buffett's investment framework as a discipline lens when weighing a buy, hold, or sell decision — circle of competence, economic moat, owner earnings & intrinsic value, margin of safety, management/capital-allocation quality, and market psychology (Mr. Market, fear vs greed, temperament). Use when asked to "run this through Buffett", "what would Buffett say", "does this pass the moat test", "is this cheap enough", or for a second, more skeptical read on a name being evaluated or already held. This is a discipline overlay, not a replacement for a strategy — it applies the Buffett lens to how someone actually invests, rather than issuing generic advice.

2016judea/image-riff

Turn one or more reference images into original art in that reference's own visual language, then cut it to whatever surface it's for. Use when you paste or point at art and say "use this as the base image", "generate art from this", "riff on this", "some creative ideation with these images", "make me a channel banner / avatar / cover / plate", "wilder version of this", or want a spread of options off one piece of reference. This is the TASK skill; the engine is the `make-art` tool skill.

2016judea/leonardo

Draw the way Leonardo da Vinci drew — a study sheet, a notebook folio, a red-chalk or silverpoint study, a machine cutaway, a storm of vortices — in his real materials and page-logic, generated with the make-art engine and anchored on fifteen of his actual (public-domain) sheets. Use when you say "Leonardo", "da Vinci", "like his notebooks", "a codex page of X", "draw this as one of his study sheets", "sanguine", "silverpoint", or wants a design, diagram, or illustration in that hand. Also a reading guide to his notebooks (Richter's 1883 public-domain translation) for "what did Leonardo say about shadow / trees / water". This is a TASK skill; the engine is `make-art`.

2016judea/mcp-stack

Which free MCP server or framework to reach for, and its traps — finance/gov data (SEC EDGAR, Yahoo, SAM.gov, USAspending), web research (Exa, Firecrawl, Crawl4AI, Jina reader), design/art/brand (Canva, Inkscape, Penpot, Figma, Orshot, Hugging Face image gen, vectorizing, charts), data/spatial (DuckDB spatial, live ArcGIS layers, OpenStreetMap/Overpass, Census, MapLibre), and ops (PostHog, iMessage, context7 docs). Use when making a social post, OG card, poster, logo/vector, chart, map, or brand asset; when querying parquet/geojson/duckdb or a city's open-data layer; when an MCP "needs authentication" or fails; or when asked "what tools do we have", "is there an MCP for X", "should we add X".

2016judea/records-request

Get a specific record out of a US government office by public-records request — "request the assessor's model", "file a data practices request", "FOIA this", "open records request", "can we just ask the county for it", "who do I write to at <county>", "chase that request", "did they ever answer". Covers checking the website first, finding the right office and statute, the carve-out paragraph that makes a request answerable instead of refused, web-form traps (hidden character caps, WAFs that reject apostrophes), chasing (there is usually no deadline), whether what comes back may be republished, and parsing multi-year tables without silent errors.

2016judea/sms-native-product

Build a product whose interface is text messages rather than an app or a website — "no app, no website", "they just text a number", "chat with our agent natively in Text Messages", "can we do this over text", "an SMS bot", "a Telegram bot", "make it a group chat", "minimum viable friction". Fires equally when it has already gone wrong — "my campaign got rejected", "our number is blocked", "the texts aren't arriving", "why do I need to register". Covers the gate that decides whether such a product can send at all (US A2P 10DLC registration, SHAFT content rules, permanent rejection codes), group MMS from code, what each channel can't do, an architecture that survives losing the channel, and guarding model-rewritten user content.

2016judea/vertical-market-agent

Build a chat agent that knows one industry in one metro better than any general model because it carries a precomputed digest of real public records (or a mined review corpus) and can pull live records mid-conversation — finding the moat, building a byte-stable substrate, enumerating what the records can't, the data traps that produce plausible wrong numbers, deterministic math in tools, measured prompt cost and cache TTL, shipping as an ad destination, an off-sector ending, and a precomputed spatial "what is this next to" layer. Use when building a vertical AI agent grounded in records rather than general knowledge.

관련 스킬