10/24/2025

Releasing n8n-nodes-signal-cli - How I automatically transcribe Signal voice messages with my own n8n node extension

I was fed up with receiving 5-minute voice messages on Signal just to find out someone was asking if I'm free next Tuesday. No automatic transcription, no way to quickly scan the content. You have to listen to the whole thing, often at the worst possible moment.

So I built n8n-nodes-signal-cli - an n8n extension that integrates with Signal CLI to automatically transcribe voice messages and send back a concise summary directly in the conversation.

The problem

Voice messages suck when:

  • People take 5 minutes to say what could be written in 3 lines
  • You're in a meeting and can't listen
  • You need to find specific information buried in a long monologue
  • Signal doesn't offer automatic transcription

The solution

My n8n extension adds two nodes:

  • Signal CLI Trigger: fires when receiving new Signal messages
  • Signal CLI: sends messages back to Signal

My workflow:

Signal message received 
    → Filter voice messages only
    → Download audio file
    → Transcribe with local Whisper (or equivalent)
    → Summarize with LLM
    → Send transcript back to Signal conversation
    

Result: That 3-minute rambling voice message becomes:

📝 Transcript: "Are you available next Tuesday at 2 PM for a meeting?"

My self-hosted n8n runs on my NAS locked behind a Zero Trust Network thanks to France nuage

Installation

Prerequisites:

  • n8n installed and running
  • signal-cli configured with your phone number

Install the extension:

npm install n8n-nodes-signal-cli

Setup:

  1. Add Signal CLI credentials in n8n
  2. Create new workflow
  3. Add "Signal CLI Trigger" node
  4. Build your processing logic
  5. Use "Signal CLI" node to send messages back

Beyond transcription

This opens up tons of automation possibilities:

  • Reminder bot - schedule reminders via Signal
  • Auto-archiving - save important messages automatically
  • Instant translation - translate messages on the fly
  • Smart notifications - filter and route messages by content
  • Service integration - connect Signal to Slack, Discord, etc.

Results

Since using this:

  • I never miss important info hidden in long voice messages
  • I can "read" voice messages anywhere, anytime
  • People actually appreciate seeing their rambling transcribed concisely
  • Saved tons of time not listening to minutes of audio

Check it out on GitHub. Star it if you find it useful. Report bugs. Send PRs. The usual drill.

8/04/2023

Filtrer les messages de sensibilisation à la cybersécurité et aux phishing de avantdecliquer.com

Si tu travailles pour de grands groupes, tu as peut-ĂȘtre dĂ©jĂ  entendu parler de https://avantdecliquer.com/

Cette plateforme aide les entreprises Ă  sensibiliser leurs salariĂ©s aux dangers du phishing en leur envoyant des faux e-mails de phishing. 

Alors, comment gérer ce flux d'emails sans se noyer, surtout si, comme moi, tu reçois déjà entre 150 et 200 e-mails chaque jour ?

Pas de panique ! Si tu sais dĂ©jĂ  repĂ©rer ces faux-emails et souhaite organiser ta boĂźte de rĂ©ception plus efficacement, suis le guide ci-dessous. 

J'ai préparé une démo pour te montrer comment créer un filtre sur Outlook afin d'archiver automatiquement les messages provenant de avantdecliquer.com.

2/09/2023

How to add a label to previously created annotation in MakeSense.ai when you forgot to select a default one

Yes. Like the title said.


function selectOption(f){
  const a = document.querySelector('.DropdownOption');
    if(a===null){
        return setTimeout(selectOption.bind(null, f), 1);
    }

    a.click();

    setTimeout(f, 1);    
}

function selectLabel(label, f){
    label.click();
    selectOption(f);
}

function selectLabels(labels, f){
  function _do(){
    if(labels.length === 0){
        return f();
    }

    const l = labels.shift();
    selectLabel(l, _do);
  }

  _do();   
}

function selectAll(f){
  selectLabels(Array.from(document.querySelectorAll('.DropdownLabel')), f);
}

function loop(){
  if(document.querySelector('[draggable="false"][alt="next"]') !== null){
    console.log('Done!');
    return;
  }
  
  selectAll(() => {
      document.querySelector('[alt="next"]').click();
      setTimeout(loop, 100);
  })
}

loop();
»
 
 
Made with on a hot august night from an airplane the 19th of March 2017.