소스 정보
- 저장소
- SkeneTechnologies/skene
- 최근 소스 활동
- 2026년 4월 11일 18:36
- 감지된 SKILL.md 언어
- 영어
- 스타
- 121
- 포크
- 13
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/SkeneTechnologies/skene --skill comms명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SOC 직업 분류 기준
SKILL.md 표시 중
| name | comms |
| description | Polymorphic conversation threads and messages for any entity |
Conversation threads and messages that attach to any entity (contact, company, deal, ticket, task, or project) via a polymorphic relationship.
| Column | Type | Description |
|---|---|---|
| id | uuid | Primary key, auto-generated |
| org_id | uuid | References organizations. CASCADE on delete |
| entity_type | text | What this thread attaches to. Checked against allowed values |
| entity_id | uuid | ID of the related entity. No FK enforced for polymorphism |
| subject | text | Optional thread subject line |
| channel | channel_type | Communication channel (email, sms, etc.) |
| is_closed | boolean | Whether the thread is closed, defaults to false |
| created_at | timestamptz | Row creation time |
| updated_at | timestamptz | Auto-updated on change via trigger |
| metadata | jsonb | Freeform JSON, defaults to empty object |
Allowed entity_type values: contact, company, deal, ticket, task, project.
| Column | Type | Description |
|---|---|---|
| id | uuid | Primary key, auto-generated |
| org_id | uuid | References organizations. CASCADE on delete |
| thread_id | uuid | References threads. CASCADE on delete |
| author_id | uuid | References users. SET NULL on delete |
| contact_id | uuid | References contacts. SET NULL on delete |
| direction | message_direction | Inbound, outbound, or internal. Defaults to 'internal' |
| body | text | Plain text message body (required) |
| html_body | text | Rich HTML version of the message body |
| external_id | text | ID from external system, e.g. email Message-ID |
| sent_at | timestamptz | When the message was sent, defaults to now() |
| created_at | timestamptz | Row creation time |
| updated_at | timestamptz | Auto-updated on change via trigger |
| metadata | jsonb | Freeform JSON, defaults to empty object |
| Value | Description |
|---|---|
| inbound | Message received from an external party |
| outbound | Message sent to an external party |
| internal | Internal note or comment |
Shared with the support skill. Defined with a guard (CREATE TYPE IF NOT EXISTS pattern) so it works whether or not support is installed.
| Value | Description |
|---|---|
| Email channel | |
| sms | SMS / text message |
| chat | Live chat or messaging |
| phone | Phone call |
| social | Social media |
Both tables have RLS enabled and scoped to org_id via get_user_org_id(). SELECT, INSERT, and UPDATE are open to all org members. DELETE requires admin privileges via is_admin().
-- Full conversation history for a contact
SELECT
th.entity_type,
th.entity_id,
m.direction,
coalesce(u.full_name, c.first_name || ' ' || coalesce(c.last_name, '')) AS sender,
m.body,
m.sent_at
FROM threads th
JOIN messages m ON m.thread_id = th.id
LEFT JOIN users u ON u.id = m.author_id
LEFT JOIN contacts c ON c.id = m.contact_id
WHERE th.entity_type = 'contact' AND th.entity_id = '<contact_id>'
ORDER BY m.sent_at ASC;
-- Recent inbound messages across all threads
SELECT
th.entity_type,
th.entity_id,
th.subject,
th.channel,
m.body,
m.sent_at,
c.first_name || ' ' || coalesce(c.last_name, '') AS from_contact
FROM messages m
JOIN threads th ON th.id = m.thread_id
LEFT JOIN contacts c ON c.id = m.contact_id
WHERE m.direction = 'inbound'
ORDER BY m.sent_at DESC
LIMIT 50;
-- Threads with no reply (inbound message but no outbound response)
SELECT
th.id AS thread_id,
th.entity_type,
th.entity_id,
th.subject,
th.channel,
min(m.sent_at) AS first_message_at
FROM threads th
JOIN messages m ON m.thread_id = th.id
WHERE th.is_closed = false
AND m.direction = 'inbound'
AND NOT EXISTS (
SELECT 1 FROM messages m2
WHERE m2.thread_id = th.id
AND m2.direction = 'outbound'
AND m2.sent_at > m.sent_at
)
GROUP BY th.id, th.entity_type, th.entity_id, th.subject, th.channel
ORDER BY first_message_at ASC;
-- Message volume by channel and direction (last 30 days)
SELECT
th.channel,
count(*) FILTER (WHERE m.direction = 'inbound') AS inbound,
count(*) FILTER (WHERE m.direction = 'outbound') AS outbound,
count(*) FILTER (WHERE m.direction = 'internal') AS internal,
count(*) AS total
FROM messages m
JOIN threads th ON th.id = m.thread_id
WHERE m.sent_at >= now() - interval '30 days'
GROUP BY th.channel
ORDER BY total DESC;
-- Open threads per entity type with message counts
SELECT
th.entity_type,
count(DISTINCT th.id) AS open_threads,
count(m.id) AS total_messages,
max(m.sent_at) AS last_activity
FROM threads th
LEFT JOIN messages m ON m.thread_id = th.id
WHERE th.is_closed = false
GROUP BY th.entity_type
ORDER BY open_threads DESC;