Skip to content

thoughtoinnovate/tark

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

107 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

tark

AI-powered CLI agent with TUI chat interface and Neovim integration.

Features

  • TUI Chat Interface: Interactive terminal chat with AI assistant
  • Editor Adapters: Neovim adapter now lives in the plugins monorepo and uses editor adapter APIs
  • File Operations: Read, write, and search files through chat
  • Shell Commands: Execute commands directly from chat
  • Image Attachments: Paste images from clipboard with Ctrl-v
  • Multi-Provider: Supports Claude (Anthropic), OpenAI, Google (Gemini), GitHub Copilot, and local Ollama models
  • Usage Dashboard: Track costs, tokens, and sessions with interactive web dashboard
  • Agent Modes: Ask (read-only), Plan (propose changes), Build (full access)
  • Approval System: Approve risky operations with pattern matching

Quick Install

# Option 1: Binary install (Linux/macOS)
curl -fsSL https://raw.githubusercontent.com/thoughtoinnovate/tark/main/install.sh | bash

Installation

1. Install the tark Binary

Option A: Install Script (Recommended)

curl -fsSL https://raw.githubusercontent.com/thoughtoinnovate/tark/main/install.sh | bash

Option B: Manual Download

Download from GitHub Releases:

Platform Binary
Linux x64 tark-linux-x86_64
Linux ARM64 tark-linux-arm64
macOS Intel tark-darwin-x86_64
macOS Apple Silicon tark-darwin-arm64
Windows x64 tark-windows-x86_64.exe
# Example: Linux
curl -L https://github.com/thoughtoinnovate/tark/releases/latest/download/tark-linux-x86_64 -o tark
chmod +x tark
sudo mv tark /usr/local/bin/

Option C: Build from Source

cargo install --git https://github.com/thoughtoinnovate/tark.git

Verify Installation

tark --version

2. Set API Key

# For OpenAI
export OPENAI_API_KEY="your-api-key"

# Or for Claude
export ANTHROPIC_API_KEY="your-api-key"

# Or for Google Gemini
export GEMINI_API_KEY="your-api-key"

# Or for GitHub Copilot (Device Flow OAuth)
tark auth copilot

# Or for local Ollama (no key needed)
ollama serve

3. Install Neovim ACP Plugin

Neovim adapter source has moved to the plugins monorepo: ../plugins/tark/editors/neovim (repository path thoughtoinnovate/plugins/tark/editors/neovim).

Local checkout (Recommended for now)

return {
    dir = "~/code/plugins/tark/editors/neovim",
    lazy = false,
    keys = {
        { "<leader>ac", "<cmd>AcpChatToggle<cr>", desc = "Toggle ACP chat" },
    },
}

The adapter plugin automatically downloads the correct binary for your platform.

Lazy.nvim from monorepo

return {
    url = "https://github.com/thoughtoinnovate/plugins",
    name = "tark-editors",
    lazy = false,
    init = function(plugin)
        vim.opt.rtp:prepend(plugin.dir .. "/tark/editors/neovim")
    end,
    keys = {
        { "<leader>ac", "<cmd>AcpChatToggle<cr>", desc = "Toggle ACP chat" },
    },
}

Note: Git-based plugin managers clone repositories, not single folders. For minimal checkout size use sparse checkout and the local dir config:

git clone --filter=blob:none --sparse https://github.com/thoughtoinnovate/plugins.git
cd plugins
git sparse-checkout set tark/editors/neovim

Full Config (all options)

return {
    dir = "~/code/plugins/tark/editors/neovim",
    lazy = false,
    keys = {
        { "<leader>ac", "<cmd>AcpChatToggle<cr>", desc = "Toggle ACP chat" },
        { "<leader>ao", "<cmd>AcpChatOpen<cr>", desc = "Open ACP chat" },
        { "<leader>ax", "<cmd>AcpChatClose<cr>", desc = "Close ACP chat" },
    },
    opts = {
        -- ACP transport settings
        acp = {
            command = "tark", -- nil => auto-detect
            args = { "acp" },
            env = {},
            cwd = nil,
            protocol_version = 1,
            profile = "auto", -- auto | generic | tark_extension
            client_capabilities = {
                fs = { readTextFile = false, writeTextFile = false },
                terminal = false,
            },
        },

        -- ACP widget settings
        chat = {
            mode = 'ask',        -- ask | plan | build
            timeout_ms = 15000,
            window = {
                position = 'right',
                width = 0.4,
                height = 0.5,
            },
        },

        -- Auto-download binary if not found
        auto_download = true,

        -- Ghost text settings (inline suggestions like Copilot)
        ghost = {
            enabled = true,  -- Enable ghost text completions
            auto_trigger = true,  -- Auto-trigger on typing
            debounce_ms = 300,  -- Debounce delay
            accept_key = '<Tab>',  -- Key to accept suggestion
        },

        -- LSP settings for completion menu (optional, disabled by default)
        lsp = {
            enabled = false,  -- Enable LSP for nvim-cmp integration
            exclude_filetypes = { 'TelescopePrompt', 'NvimTree', 'neo-tree' },
        },
    },
}

Commands

ACP Chat Commands (Neovim)

Command Description
:AcpChatToggle Toggle ACP chat widget
:AcpChatOpen Open ACP chat widget
:AcpChatClose Close ACP chat widget
:AcpSend [message] Send from input pane or argument
:AcpCancel Cancel active ACP request
:AcpAskBuffer [question] Send current buffer as ACP context and ask
:'<,'>AcpAskSelection [question] Send selected lines as ACP context and ask
:AcpMode ask|plan|build Set ACP session mode
:AcpConfigSet <configId> <value> Set ACP session configuration
:AcpUiFocus transcript|input|interaction Set ACP widget focus
:AcpUiNextAction Select next interactive action
:AcpUiPrevAction Select previous interactive action
:AcpUiSubmit Activate selection or send input
:AcpUiCancel Cancel active interaction
:TarkDownload Download tark binary
:TarkVersion Show tark version

Legacy :Tark* chat commands remain available as compatibility aliases during migration.

Ghost Text Commands (Inline Suggestions)

Command Description
:TarkGhostEnable Enable ghost text suggestions
:TarkGhostDisable Disable ghost text suggestions
:TarkGhostToggle Toggle ghost text on/off
:TarkGhostUsage Show ghost text usage stats

Usage: Type in insert mode and suggestions appear as grey text. Press <Tab> to accept.

LSP Commands (Completion Menu)

Command Description
:TarkLspStart Start tark LSP server
:TarkLspStop Stop tark LSP server
:TarkLspRestart Restart tark LSP server
:TarkLspStatus Show tark LSP status
:TarkLspEnable Enable LSP completions
:TarkLspDisable Disable LSP completions
:TarkLspToggle Toggle LSP completions on/off
:TarkLspUsage Show LSP usage stats

Usage

Standalone (Terminal)

# Start chat in any terminal
tark chat

# With specific model
tark chat --model gpt-4o

# Start ACP server on stdio (Content-Length JSON-RPC v2 for editor clients)
tark acp --cwd .

# In a specific directory
cd /my/project && tark chat

ACP cutover note:

  • Legacy ACP methods (session/create, session/send_message) are removed.
  • Prompt streaming is normalized to session/update lifecycle events.
  • Inline completion uses tark/inline_completion ACP extension (no HTTP fallback).

In Neovim

Press <leader>tc (or your configured keymap) to toggle the chat window.

Slash Commands

Command Description
/help Show all available commands
/model Open provider/model picker
/provider Open provider picker
/theme Open theme picker with live preview
/diff [auto|inline|split] Set diff preview mode
/ask Switch to Ask mode (read-only)
/plan Switch to Plan mode (propose changes)
/build Switch to Build mode (full access)
/trust Open trust level selector
/clear Clear chat history
/clear-costs Reset session usage totals
/compact Manually compact context window
/attach <file> Attach a file to context
/file Open file picker
/sessions List all sessions
/session <id> Switch to specific session
/new Start a new session
/export [path] Export session to JSON
/import <path> Import session from JSON
/tools Show available tools
/plugins Show installed plugins
/usage Show usage statistics
/exit Close chat

Keyboard Shortcuts

Global

Key Description
Ctrl+C Cancel LLM request / Quit (when idle)
Ctrl+Q Quit application
Ctrl+? Toggle help modal
Tab Cycle focus (Input → Messages → Sidebar)
Shift+Tab Cycle agent mode (Build → Plan → Ask)
Ctrl+B Toggle sidebar visibility
Ctrl+T Toggle model-level thinking
Ctrl+M Cycle build mode (Manual → Balanced → Careful)
Ctrl+Shift+B Open trust level selector (Build mode only)
Esc Close modal / Cancel operation
Esc Esc Cancel ongoing agent operation (double-tap)

Input Area

Key Description
Enter Send message
Shift+Enter Insert newline
Ctrl+Left/Right Word navigation
Home/End Line start/end
Up/Down Input history navigation
@ Open file picker for attachments (Enter toggles, Esc closes)
Ctrl+V Paste text or attach clipboard image

Selected files and folders are inserted into the prompt as @path tokens. Removing a token from the prompt clears the matching attachments; folders appear as a single token with their file count.

Message Area (Vim-style)

Key Description
j/k Move focus to next/previous message
v Start visual selection in focused message
h/l Move cursor left/right (message selection)
w/b Next/previous word (message selection)
0/$ Line start/end (message selection)
y Yank selection (visual) / yank message (normal)
Enter Toggle collapse for focused tool/group or tool item
Right Enter a tool group
- Exit a tool group

Sidebar Navigation

Key Description
j/k Navigate items
Enter Expand/collapse panel or select item
h/l Exit/enter panel
d Delete context file (in Context panel)
e Edit task (in Tasks panel)
D Delete task (in Tasks panel)
J/K Move task up/down (in Tasks panel)

Agent Modes

Mode Access Use For
Ask Read-only Explore, analyze, understand code
Plan Read-only + propose Propose changes as diffs without applying
Build Full access Execute changes, run commands

Diff previews render inline on narrow terminals and side-by-side when there is enough width.

Trust Levels (Build Mode)

Control how risky operations are approved. Use /trust command or Ctrl+Shift+B in Build mode:

Trust Level Description
Manual All tool executions require explicit approval
Balanced Auto-approve reads; prompt for writes and risky ops (default)
Careful Auto-approve most ops; only prompt for dangerous operations

When prompted for approval, you can:

  • Y - Approve once
  • S - Approve for this session (pattern-matched)
  • A - Always approve (persisted to .tark/approvals.json)
  • N - Deny once
  • D - Always deny (persisted)

Task Queue

When you send multiple messages while the agent is working, they're queued and processed in order.

Managing queued tasks (in Sidebar → Tasks panel):

  • e - Edit a queued task before it runs
  • D - Delete a queued task
  • J/K - Reorder tasks in the queue

Context & Archives

When context is compacted, Tark keeps the latest summary in the active conversation and archives older messages. Archived chunks can be loaded from the top of the message list; they are UI-only and not sent to the LLM.

CLI Usage

# Start TUI chat
tark chat

# Show usage statistics
tark usage

# Serve HTTP API
tark serve --port 8765

# Show version
tark --version

Health Check

:checkhealth tark

Configuration

CLI Config (~/.config/tark/config.toml)

[llm]
# Default provider (tark_sim is built-in for testing, no API key required)
default_provider = "tark_sim"

[llm.tark_sim]
model = "tark_llm"
max_tokens = 8192

[llm.openai]
model = "gpt-4o"
max_tokens = 4096

[llm.claude]
model = "claude-sonnet-4-20250514"

[llm.ollama]
model = "codellama"

[server]
port = 8765

[tui]
theme = "catppuccin_mocha"
plugin_widget_poll_ms = 2000
session_usage_poll_ms = 1000

[tools]
shell_enabled = true
tool_timeout_secs = 60

Tool calls can override the default timeout by including timeout_secs in their arguments.

Project Config (.tark/)

Create .tark/ in your project for local settings:

.tark/
├── config.toml      # Project settings
├── rules/           # Custom instructions
│   └── style.md
└── conversations/   # Saved sessions

Statusline Integration

Show Tark status in your statusline with a nice icon:

With Lualine

require('lualine').setup({
    sections = {
        lualine_x = {
            -- Full: icon + "tark"
            require('tark.statusline').lualine,
            
            -- Or compact: icon only
            -- require('tark.statusline').lualine_icon,
        }
    }
})

Manual Statusline

-- In your statusline string
vim.o.statusline = "%f %m %= %{%v:lua.require('tark.statusline').status()%}"

-- Or with highlights
vim.o.statusline = "%f %m %= " .. require('tark.statusline').status_with_hl()

Status Icons (Nerd Fonts)

Icon Status Meaning
󱙺 Active Completions working
󰊠 Idle Ready, no recent activity
󰌆 No Key Missing API key
󰚌 Disabled Ghost text disabled
Error Binary not found

Docs

Setup & Configuration

Customization

Architecture

Development

Architecture

The TUI uses a Backend-for-Frontend (BFF) architecture separating UI from business logic:

┌─────────────────────────────────────────────────────────┐
│                    Presentation Layer                    │
│  ┌───────────────────────────────────────────────────┐  │
│  │              TuiRenderer (ratatui)                │  │
│  │   • Widgets: Header, Messages, Input, Sidebar     │  │
│  │   • Modals: Provider, Model, Theme, Help, etc.    │  │
│  └───────────────────────┬───────────────────────────┘  │
└──────────────────────────┼──────────────────────────────┘
                           │ Commands / Events
                           ▼
┌─────────────────────────────────────────────────────────┐
│                      BFF Layer                           │
│  ┌─────────────────┐  ┌─────────────────┐              │
│  │  TuiController  │─▶│   AppService    │              │
│  └─────────────────┘  └────────┬────────┘              │
│                                │                        │
│  ┌─────────────────────────────┼─────────────────────┐ │
│  │              SharedState (Arc<RwLock>)            │ │
│  │   • messages, streaming, provider, model          │ │
│  │   • agent_mode, build_mode, trust_level           │ │
│  │   • sidebar_data, context_files, tasks            │ │
│  └───────────────────────────────────────────────────┘ │
└────────────────────────────┬────────────────────────────┘
                             │
┌────────────────────────────┼────────────────────────────┐
│                     Domain Layer                         │
│  ┌──────────────┐  ┌─────────────┐  ┌────────────────┐ │
│  │  ChatAgent   │  │   Tools     │  │  LLM Provider  │ │
│  │  + Context   │  │  Registry   │  │   (multiple)   │ │
│  └──────────────┘  └─────────────┘  └────────────────┘ │
└─────────────────────────────────────────────────────────┘

See BFF Architecture for details.

Plugins

Tark supports a WASM-based plugin system for extending functionality.

Plugin Management

# List installed plugins
tark plugin list

# Install a plugin from git
tark plugin add https://github.com/user/tark-plugin

# Update a plugin from its recorded source
tark plugin update <plugin-id>
tark plugin update --all

# Show plugin details
tark plugin info <plugin-id>

# Run OAuth for a plugin
tark plugin auth <plugin-id>

# Enable/disable plugins
tark plugin enable <plugin-id>
tark plugin disable <plugin-id>

# Uninstall a plugin
tark plugin remove <plugin-id>

Plugin Types

Type Purpose
auth Add authentication methods (OAuth, API keys)
tool Add agent capabilities
provider Add LLM providers
channel Add messaging channels (Slack, Discord, Signal)
hook Lifecycle event handlers

Remote Channels

Run channel plugins in remote mode to steer Tark from chat systems:

# Interactive TUI + Discord control
tark --remote discord

# Headless remote mode (prints live events to stdout)
tark --headless --remote discord

# Inspect or manage remote sessions
tark show all
tark show <session-id>
tark stop <session-id>
tark resume <session-id>

From your channel (Discord/Slack/etc.), you can also run /tark interrupt to cancel a running task. If a remote prompt requires input, the local TUI will surface it and you can reply from the TUI prompt or from the remote channel.

Remote access is gated by allowlists in .tark/config.toml:

[remote]
http_enabled = false
max_message_chars = 1800
allowed_plugins = ["discord"]
allowed_users = ["1234567890"]
allowed_guilds = ["0987654321"]
allowed_channels = ["55555555"]
allowed_roles = ["role-id"]
allow_model_change = true
allow_mode_change = true
allow_trust_change = false
require_allowlist = true

Logs are written to .tark/logs/remote (error-only by default; use --remote-debug for full logs).

See docs/REMOTE_CHANNELS.md for Discord setup details.

Building Plugins

Security

  • API keys are only sent to official provider endpoints
  • No telemetry; usage/cost tracking is stored locally (.tark/usage.db)
  • Model metadata/pricing fetched from models.dev for capability detection (no API keys sent)
  • Local Ollama option for fully offline LLM usage
  • All binaries are built via GitHub Actions (transparent, auditable)
  • SHA256 checksums for all release artifacts
  • Plugins run in WASM sandbox with capability-based security

License

Apache-2.0 - See LICENSE for details.

About

The smart agent

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors