axis-crm 1.0.0 → 1.0.2

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.
package/README.md CHANGED
@@ -2,90 +2,123 @@
2
2
 
3
3
  A git-based CRM for freelancers and small teams.
4
4
 
5
- Axis CRM stores all your client data as Markdown files with YAML frontmatter. It works in any text editor, is optimized for [Obsidian](https://obsidian.md) with the Dataview plugin, and supports automation through n8n workflows. All data is versioned in git — no database, no vendor lock-in.
5
+ Manage your clients, projects, meetings, contacts, rates, and files all as Markdown in a git repo. No database, no SaaS, no vendor lock-in.
6
+
7
+ Works in any text editor. Optimized for [Obsidian](https://obsidian.md) with Dataview dashboards. Supports automation through n8n workflows.
8
+
9
+ ## Quick Start
10
+
11
+ ```bash
12
+ npx axis-crm init
13
+ cd crm
14
+ git init && git add -A && git commit -m "init: axis-crm"
15
+ ```
16
+
17
+ That's it. You have a working CRM. Open in Obsidian and open `CRM Dashboard.md`.
6
18
 
7
19
  ## Why
8
20
 
9
- Most CRMs are built for sales teams of 50+. If you're a freelancer or a small agency, you don't need Salesforce — you need a system that's fast, local, and doesn't cost $50/month per seat.
21
+ You're a freelancer. You have 5-10 clients. You need to know:
22
+
23
+ - Who are my contacts at each client?
24
+ - What projects am I working on and what's their status?
25
+ - What did we agree on in the last meeting?
26
+ - What's my hourly rate for this client?
27
+ - Where's the contract?
28
+
29
+ You don't need Salesforce, HubSpot, or a $50/month tool. You need a folder structure that makes sense, with version history and zero maintenance.
10
30
 
11
31
  Axis CRM gives you:
12
- - **Full ownership** — your data lives in a git repo, not someone else's server
13
- - **Version history** — every change is a commit, every deleted lead is recoverable
14
- - **Markdown-native** — works with Obsidian, VS Code, Vim, or any editor
15
- - **Automation-ready** — n8n workflows for meeting transcripts and client research
16
- - **AI-friendly** — CLAUDE.md included, works with Claude Code and other AI tools out of the box
17
32
 
18
- ## Structure
33
+ - **One folder per client** — contacts, meetings, projects, communication, files, all in one place
34
+ - **Billing rates** — track hourly/daily rates per client in frontmatter
35
+ - **Meeting notes** — auto-saved from Fireflies via n8n (or add manually)
36
+ - **Project tracking** — scope, briefs, deliverables, timeline per project
37
+ - **Version history** — every change is a git commit, nothing is ever lost
38
+ - **Dashboards** — Obsidian Dataview queries show you everything at a glance
39
+ - **AI-ready** — CLAUDE.md included, works with Claude Code and Cursor out of the box
40
+
41
+ ## What a Client Looks Like
19
42
 
20
43
  ```
21
- axis-crm/
22
- clients/ # each client = a folder
23
- acme-consulting/ # demo client
24
- README.md # client overview (status, contacts, rates)
25
- contacts/ # people at the company
26
- meetings/ # meeting notes (auto-filled from Fireflies)
27
- projects/ # project folders (scope, briefs, deliverables)
28
- communication/ # key decisions and agreements
29
- files/ # contracts, proposals, invoices
30
- leads/ # each lead = a single .md file
31
- templates/ # templates for all record types
32
- rules/ # lifecycle, scoring, field definitions
33
- scripts/ # shell scripts for common operations
34
- automations/ # n8n workflow exports (JSON)
35
- dashboards/ # Obsidian Dataview dashboards
36
- CRM Dashboard.md # main dashboard
44
+ clients/acme-consulting/
45
+ README.md # overview, status, rates, industry
46
+ contacts/
47
+ jana-novakova.md # name, role, email, phone, notes
48
+ tomas-dvorak.md
49
+ meetings/
50
+ 2026-02-10-kickoff.md # agenda, notes, action items, transcript
51
+ 2026-03-15-review.md
52
+ projects/
53
+ web-redesign/
54
+ README.md # scope, timeline, status, value
55
+ brief.md # client brief
56
+ deliverables/
57
+ notes/
58
+ communication/
59
+ 2026-03-01-price-agreed.md # key decisions and agreements
60
+ files/
61
+ contracts/
62
+ proposals/
63
+ invoices/
37
64
  ```
38
65
 
39
- ## Quick Start
66
+ Every file uses YAML frontmatter for structured data. Git gives you the history.
40
67
 
41
- ```bash
42
- npx axis-crm init
43
- cd crm
44
- git init && git add -A && git commit -m "init: axis-crm"
68
+ ## Billing Rates
69
+
70
+ Track what each client pays you:
71
+
72
+ ```yaml
73
+ # in clients/acme-consulting/README.md frontmatter
74
+ hourly_rate: 120
75
+ manday_rate: 960
76
+ currency: 'USD'
45
77
  ```
46
78
 
47
- That's it. You have a working CRM.
79
+ Query across all clients in Obsidian: "show me clients sorted by hourly rate" — just works with Dataview.
48
80
 
49
- Open in [Obsidian](https://obsidian.md) (install [Dataview](https://github.com/blacksmithgu/obsidian-dataview) plugin) and open `CRM Dashboard.md` to see your pipeline.
81
+ ## Structure
50
82
 
51
- Create your first lead:
52
- ```bash
53
- ./scripts/new-lead.sh "Acme Corp"
54
83
  ```
55
-
56
- Or clone manually:
57
- ```bash
58
- git clone https://github.com/PatrikSchick-AI/axis-crm.git
84
+ axis-crm/
85
+ clients/ # each client = a folder (the core of the CRM)
86
+ leads/ # potential clients (optional pipeline)
87
+ templates/ # templates for clients, contacts, meetings, projects
88
+ rules/ # field definitions, folder structure docs
89
+ scripts/ # shell scripts for common operations
90
+ automations/ # n8n workflow exports (meeting notes, research)
91
+ dashboards/ # Obsidian Dataview dashboards
92
+ CRM Dashboard.md # main overview
93
+ CLAUDE.md # AI agent instructions
59
94
  ```
60
95
 
61
96
  ## Scripts
62
97
 
63
- | Script | Description | Usage |
64
- | --- | --- | --- |
65
- | `new-lead.sh` | Create a new lead from template | `./scripts/new-lead.sh "Company Name"` |
66
- | `convert-to-client.sh` | Convert a lead to a full client folder | `./scripts/convert-to-client.sh company-slug` |
67
- | `new-project.sh` | Create a new project for a client | `./scripts/new-project.sh client-slug "Project Name"` |
68
- | `validate.sh` | Validate all leads and clients | `./scripts/validate.sh` |
69
-
70
- All scripts support `--help` or will prompt interactively when run without flags.
98
+ | Script | What it does |
99
+ | --- | --- |
100
+ | `new-project.sh` | Create a new project for a client |
101
+ | `validate.sh` | Check all clients for required fields and structure |
102
+ | `new-lead.sh` | Create a new lead (for the optional pipeline) |
103
+ | `convert-to-client.sh` | Convert a lead into a full client folder |
71
104
 
72
- ## Lead Lifecycle
105
+ ```bash
106
+ # Add a new project to a client
107
+ ./scripts/new-project.sh acme-consulting "Mobile App"
73
108
 
74
- ```
75
- new → enriched → qualified → contacted → responded → opportunity → client
109
+ # Validate your CRM data
110
+ ./scripts/validate.sh
76
111
  ```
77
112
 
78
- Each stage has required fields and a score threshold. Leads are scored 0-100 based on data completeness, industry fit, and engagement. Details in `rules/lifecycle.md` and `rules/scoring.md`.
79
-
80
113
  ## Automations
81
114
 
82
- Two n8n workflows are included as importable JSON:
115
+ Two optional n8n workflows are included:
83
116
 
84
- - **Meeting to CRM** — Fireflies webhook triggers automatic meeting notes saved to the client folder. Uses AI (Claude) to identify the client, extract action items, and generate a summary. Supports upsert (won't fail on duplicate meetings).
117
+ **Meeting to CRM** — Fireflies records a meeting, webhook fires, AI (Claude) identifies the client, extracts a summary and action items, and commits the meeting notes to the right client folder. Automatically.
85
118
 
86
- - **Client Research** — Send a company name + URL, get back a full client profile with web scrape, AI analysis, and ARES verification (Czech business registry). Calculates a lead score automatically.
119
+ **Client Research** — Send a company name + website URL, get back a structured client profile with contacts, services, and business registry data.
87
120
 
88
- Setup instructions in [`automations/README.md`](automations/README.md).
121
+ Setup: [`automations/README.md`](automations/README.md)
89
122
 
90
123
  ## Dashboards
91
124
 
@@ -93,30 +126,21 @@ Requires Obsidian + [Dataview plugin](https://github.com/blacksmithgu/obsidian-d
93
126
 
94
127
  | Dashboard | Shows |
95
128
  | --- | --- |
96
- | `CRM Dashboard.md` | Active clients, hot leads, pipeline summary, recent meetings |
97
- | `dashboards/pipeline.md` | Leads grouped by lifecycle stage |
98
- | `dashboards/hot-leads.md` | Leads with score > 60 |
99
- | `dashboards/client-overview.md` | All clients with status and priority |
129
+ | `CRM Dashboard.md` | Active clients, recent meetings, overview |
130
+ | `dashboards/client-overview.md` | All clients with status, priority, rates |
131
+ | `dashboards/pipeline.md` | Lead pipeline by stage (if using leads) |
132
+ | `dashboards/hot-leads.md` | High-score leads ready for outreach |
100
133
 
101
- ## Client Rates
134
+ ## Lead Pipeline (Optional)
102
135
 
103
- Each client can track billing rates in their frontmatter:
136
+ If you also want to track potential clients before they become clients:
104
137
 
105
- ```yaml
106
- hourly_rate: 100
107
- manday_rate: 800
108
- currency: 'USD'
138
+ ```
139
+ new → enriched → qualified → contacted → responded → opportunity → client
109
140
  ```
110
141
 
111
- This makes it easy to query across clients with Dataview (e.g., "show me all clients sorted by hourly rate").
112
-
113
- ## Rules
114
-
115
- - A lead is a file. A client is a folder. Conversion is one-way.
116
- - Lead scoring: 0-100, thresholds define when a lead is ready for outreach.
117
- - All records use YAML frontmatter. Required fields depend on the lifecycle stage.
118
- - Details: [`rules/`](rules/)
142
+ Leads are scored 0-100. When a lead converts, run `convert-to-client.sh` and it becomes a full client folder. Details in `rules/`.
119
143
 
120
144
  ## License
121
145
 
122
- MIT
146
+ MIT — use it, fork it, make it yours.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "axis-crm",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "A git-based CRM for freelancers and small teams. Markdown + YAML + Obsidian + n8n.",
5
5
  "bin": {
6
6
  "axis-crm": "./cli/index.js"
@@ -56,7 +56,7 @@
56
56
  "typeVersion": 2,
57
57
  "position": [1050, 300],
58
58
  "parameters": {
59
- "jsCode": "const data = $input.first().json;\n\nconst prompt = `Analyzuj firmu a vytvor strukturovany profil.\n\nFirma: ${data.companyName}\nWeb: ${data.website}\nEmaily nalezene na webu: ${data.extractedEmails.join(', ')}\nTelefony nalezene na webu: ${data.extractedPhones.join(', ')}\n\nObsah webu (5000 znaku):\n${data.textContent.substring(0, 5000)}\n\nOdpovez POUZE validnim JSON:\n{\n \"company_name\": \"Oficialni nazev\",\n \"description\": \"1-2 vety co firma dela\",\n \"industry\": \"obor\",\n \"services\": [\"sluzba1\", \"sluzba2\"],\n \"city\": \"mesto\",\n \"country\": \"CZ/SK/DE/AT/...\",\n \"size_estimate\": \"micro/small/medium/large\",\n \"contacts\": [{\"name\": \"Jmeno\", \"role\": \"pozice\", \"email\": \"email\", \"phone\": \"tel\"}],\n \"social\": {\"linkedin\": \"\", \"facebook\": \"\"},\n \"web_quality\": \"modern/outdated/basic\",\n \"notes\": \"dalsi poznamky\"\n}`;\n\nreturn [{\n json: {\n ...data,\n aiRequestBody: JSON.stringify({\n model: 'claude-sonnet-4-20250514',\n max_tokens: 1024,\n messages: [{ role: 'user', content: prompt }]\n })\n }\n}];"
59
+ "jsCode": "const data = $input.first().json;\n\nconst prompt = `Analyze the company and create a structured profile.\n\nCompany: ${data.companyName}\nWebsite: ${data.website}\nEmails found on website: ${data.extractedEmails.join(', ')}\nPhones found on website: ${data.extractedPhones.join(', ')}\n\nWebsite content (5000 chars):\n${data.textContent.substring(0, 5000)}\n\nRespond with ONLY valid JSON:\n{\n \"company_name\": \"Official name\",\n \"description\": \"1-2 sentences about what the company does\",\n \"industry\": \"industry\",\n \"services\": [\"service1\", \"service2\"],\n \"city\": \"city\",\n \"country\": \"CZ/SK/DE/AT/...\",\n \"size_estimate\": \"micro/small/medium/large\",\n \"contacts\": [{\"name\": \"Name\", \"role\": \"position\", \"email\": \"email\", \"phone\": \"phone\"}],\n \"social\": {\"linkedin\": \"\", \"facebook\": \"\"},\n \"web_quality\": \"modern/outdated/basic\",\n \"notes\": \"additional notes\"\n}`;\n\nreturn [{\n json: {\n ...data,\n aiRequestBody: JSON.stringify({\n model: 'claude-sonnet-4-20250514',\n max_tokens: 1024,\n messages: [{ role: 'user', content: prompt }]\n })\n }\n}];"
60
60
  }
61
61
  },
62
62
  {
@@ -47,7 +47,7 @@
47
47
  "typeVersion": 2,
48
48
  "position": [850, 300],
49
49
  "parameters": {
50
- "jsCode": "const data = $input.first().json;\n\nconst prompt = `Analyzuj tento meeting a urcni ke kteremu klientovi patri.\n\nMeeting: ${data.title}\nUcastnici: ${data.participants.join(', ')}\nSummary: ${data.summary}\nTranscript (prvnich 2000 znaku):\n${data.transcript.substring(0, 2000)}\n\nOdpovez POUZE validnim JSON (bez markdown code blocku):\n{\n \"client_slug\": \"nazev-firmy-lowercase-pomlcky-bez-sro\",\n \"client_name\": \"Oficialni nazev firmy\",\n \"is_new\": true,\n \"attendees\": [\"jmeno1\", \"jmeno2\"],\n \"summary\": \"2-3 vety co se resilo\",\n \"action_items\": [\"ukol1\", \"ukol2\"],\n \"topics\": [\"tema1\", \"tema2\"]\n}`;\n\nreturn [{\n json: {\n ...data,\n aiRequestBody: JSON.stringify({\n model: 'claude-sonnet-4-20250514',\n max_tokens: 1024,\n messages: [{ role: 'user', content: prompt }]\n })\n }\n}];"
50
+ "jsCode": "const data = $input.first().json;\n\nconst prompt = `Analyze this meeting and identify which client it belongs to.\n\nMeeting: ${data.title}\nParticipants: ${data.participants.join(', ')}\nSummary: ${data.summary}\nTranscript (first 2000 chars):\n${data.transcript.substring(0, 2000)}\n\nRespond with ONLY valid JSON (no markdown code blocks):\n{\n \"client_slug\": \"company-name-lowercase-dashes-no-legal-suffix\",\n \"client_name\": \"Official company name\",\n \"is_new\": true,\n \"attendees\": [\"name1\", \"name2\"],\n \"summary\": \"2-3 sentences about what was discussed\",\n \"action_items\": [\"task1\", \"task2\"],\n \"topics\": [\"topic1\", \"topic2\"]\n}`;\n\nreturn [{\n json: {\n ...data,\n aiRequestBody: JSON.stringify({\n model: 'claude-sonnet-4-20250514',\n max_tokens: 1024,\n messages: [{ role: 'user', content: prompt }]\n })\n }\n}];"
51
51
  }
52
52
  },
53
53
  {
@@ -1,5 +1,5 @@
1
1
  ---
2
- title: 'Zadani — Web Redesign'
2
+ title: 'Brief — Web Redesign'
3
3
  created: '2026-02-10'
4
4
  type: brief
5
5
  ---
@@ -13,7 +13,7 @@ clients/company-name/
13
13
  contacts/ # people from the company
14
14
  jan-novak.md # contact person
15
15
  communication/ # key decisions and communication
16
- 2026-04-10-cena-dohodnuta.md
16
+ 2026-04-10-price-agreed.md
17
17
  files/ # documents
18
18
  contracts/ # signed contracts, NDAs, amendments
19
19
  proposals/ # price quotes, proposals
@@ -23,7 +23,7 @@ clients/company-name/
23
23
  projects/ # projects for the client
24
24
  project-name/ # each project = folder
25
25
  README.md # scope, status, timeline
26
- zadani.md # brief from the client
26
+ brief.md # brief from the client
27
27
  deliverables/ # outputs
28
28
  notes/ # ongoing notes
29
29
  ```
@@ -43,7 +43,7 @@ Important decisions and communication. NOT every email — only what changes dir
43
43
 
44
44
  - Filename format: `YYYY-MM-DD-description.md`
45
45
  - Frontmatter: date, channel (email/call/chat), participants, decision
46
- - Example: `2026-04-10-cena-dohodnuta.md` — client approved the quote
46
+ - Example: `2026-04-10-price-agreed.md` — client approved the quote
47
47
 
48
48
  ### files/
49
49
 
@@ -69,7 +69,7 @@ Meeting notes.
69
69
  Each project = its own folder.
70
70
 
71
71
  - `README.md` — scope, status, timeline, deliverables
72
- - `zadani.md` — original brief from the client
72
+ - `brief.md` — original brief from the client
73
73
  - `deliverables/` — final outputs
74
74
  - `notes/` — ongoing notes, drafts
75
75
 
@@ -70,9 +70,9 @@ mkdir -p "$CLIENT_DIR/contacts"
70
70
  mkdir -p "$CLIENT_DIR/projects"
71
71
  mkdir -p "$CLIENT_DIR/meetings"
72
72
  mkdir -p "$CLIENT_DIR/communication"
73
- mkdir -p "$CLIENT_DIR/files/smlouvy"
74
- mkdir -p "$CLIENT_DIR/files/nabidky"
75
- mkdir -p "$CLIENT_DIR/files/faktury"
73
+ mkdir -p "$CLIENT_DIR/files/contracts"
74
+ mkdir -p "$CLIENT_DIR/files/proposals"
75
+ mkdir -p "$CLIENT_DIR/files/invoices"
76
76
 
77
77
  # Create README.md from template with lead data
78
78
  sed -e "s|^title: ''|title: \"$TITLE\"|" \
@@ -51,19 +51,19 @@ sed -i '' \
51
51
  -e "s|^start: ''|start: '$TODAY'|" \
52
52
  "$PROJECT_DIR/README.md"
53
53
 
54
- # Fill in zadani.md
54
+ # Fill in brief.md
55
55
  sed -i '' \
56
- -e "s|^title: 'Zadani — '|title: 'Zadani — $PROJECT_NAME'|" \
56
+ -e "s|^title: 'Brief — '|title: 'Brief — $PROJECT_NAME'|" \
57
57
  -e "s|^created: ''|created: '$TODAY'|" \
58
- "$PROJECT_DIR/zadani.md"
58
+ "$PROJECT_DIR/brief.md"
59
59
 
60
60
  echo "Project created: $PROJECT_DIR/"
61
61
  echo ""
62
62
  echo " README.md — scope, status, timeline"
63
- echo " zadani.md — brief od klienta"
64
- echo " deliverables/ — vystupy"
65
- echo " notes/ — prubezne poznamky"
63
+ echo " brief.md client brief"
64
+ echo " deliverables/ — outputs"
65
+ echo " notes/ — ongoing notes"
66
66
  echo ""
67
67
  echo "Next steps:"
68
- echo " 1. Vyplnit zadani.md"
69
- echo " 2. Doplnit scope a timeline v README.md"
68
+ echo " 1. Fill in brief.md with client requirements"
69
+ echo " 2. Add scope and timeline to README.md"
@@ -1,5 +1,5 @@
1
1
  ---
2
- title: 'Zadani — '
2
+ title: 'Brief — '
3
3
  created: ''
4
4
  type: brief
5
5
  ---