Coder Social home page Coder Social logo

alajmo / sake Goto Github PK

View Code? Open in Web Editor NEW
642.0 8.0 24.0 2.11 MB

:robot: sake is a task runner for local and remote hosts

Home Page: https://sakecli.com

License: MIT License

Makefile 0.50% Go 88.97% Shell 1.32% Roff 9.07% Dockerfile 0.14%
cli server ssh config golang

sake's Introduction

sake


sake is a command runner for local and remote hosts. You define servers and tasks in sake.yaml file and then run the tasks on the servers.

This readme is also accessible on sakecli.com.

sake has tons of features:

  • auto-completion of tasks, servers and tags
  • SSH into servers or docker containers sake ssh <server>
  • list servers/tasks via sake list servers|tasks
  • present task output in a compact table format sake run <task> --output table
  • open task/server in your preferred editor sake edit task <task>
  • import other sake.yaml configs
  • and many more!

demo

Interested in managing your git repositories in a similar way? Check out mani!

Table of Contents

Installation

Packaging status

sake is available on Linux and Mac.

  • Binaries are available on the release page

  • via cURL

    curl -sfL https://raw.githubusercontent.com/alajmo/sake/main/install.sh | sh
  • via Homebrew

    brew tap alajmo/sake
    brew install sake
  • via MacPorts

    sudo port install sake
  • via Arch

    pacman -S sake
  • via pkg

    pkg install sake
  • Via Go

    go install github.com/alajmo/sake@latest

Auto-completion is available via sake completion bash|zsh|fish and man page via sake gen.

Building From Source

Requires go 1.19 or above.

  1. Clone the repo
  2. Build and run the executable
    make build && ./dist/sake
    
    # To build for all target platforms run (requires goreleaser CLI)
    make build-all

Usage

Create a New Sake Config

Run the following command:

$ sake init

Initialized sake in /tmp/sake
- Created sake.yaml

Following servers were added to sake.yaml

 Server    | Host
-----------+---------
 localhost | 0.0.0.0

Run Some Commands

# List all servers
$ sake list servers

 Server    | Host
-----------+---------
 localhost | 0.0.0.0

# List all tasks
$ sake list tasks

 Task | Description
------+-------------
 ping | Pong

# Run Task
$ sake run ping --all

TASK ping: Pong ************

0.0.0.0 | pong

# Count number of files in each server in parallel
$ sake exec --all --output table --strategy=free 'find . -type f | wc -l'

 Server    | Output
-----------+--------
 localhost | 1

What's Next

Check out the examples page for more advanced examples and the recipes page for a list of useful recipes.

Documentation

The MIT License (MIT)

Copyright (c) 2022 Samir Alajmovic

sake's People

Contributors

alajmo avatar codenoid avatar htaunay avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sake's Issues

Improve Tasks

This is an issue to improve the task object. I've gathered the following use-cases:

  • [ x] Return correct error exit codes when running tasks
  • to be able to access the previous exit code of the previous task
  • a summary of task execution at the end
  • want a --step mode flag or config setting to prompt before executing a task
  • Don't allow duplicate tasks/servers/specs/targets
  • Task not callable, only from another task (as not to accidently call it)
  • Hide tasks from auto-completion via hidden: true attribute
  • Silent output from task via silent: true (and flag)
  • ExecTTY should be config shell
  • Add flag default_timeout_s
  • Use chdir for tasks, work_dir for servers
  • Move limit/limitp to spec, or move order to target
  • Figure out changed/skipped/when
  • Conditional tasks (success, error, skip)
  • Add callbacks (success/error)
  • Loader show current task and how many left on table
  • Add retries to task
  • Add required envs
  • Add option to prompt for envs
  • Handle Match * in ssh config for inventory as well
  • Something similar to play, to trigger multiple tasks (with their own context)
  • Add env variables to multiple servers
  • Run one task, save output from all, and then have one task handle differences
  • Save logs/output to files (remote/local)
  • Diff task
  • Inherit default from default spec/target
  • Add yaml to command mapper
  • Implement facts
  • Configure what to show, host/ip or name, configure via theme/cli flags
  • - Template for server prefix, similar to header
  • - Add colors to describe (key bold, value color), true (green), false (red)
  • - Add Tree output
  • Fix hashed ip6 with port 22 does not work, all other combinations work
  • Fix sake ssh inv not working

A separate pull-request will be created to implement the necessary changes.

Should fail on non-zero exit

Is your feature request related to a problem? Please describe

Currently sake does not exit with non-zero code (or, simply, fail) when the command we're executing exited with non-zero code.

It'd be nice if it would fail on non-zero code.

Describe the solution you'd like

I think the feature should be optional to remain backward compatible with existing users. So, to have sake fail on non-zero exit code, the user should incite another CLI options like --fail.

Additional context

The sake command that I use to produce this issue was sake run <command> --servers <server> --known-host-file <file>

Let me know if I was wrong about the exit behavior or any needed reproductions.

Usage with sudo?

I've just found the tool and I'm very impressed, but I can't figure out how to use sudo on a remote server.
From what I've read in the documentation is supposed to run not interactively, so I could provide a password with sudo -S.
Considering that I'm running a script only on one server at a time I'd rather have an interactive session, which seems to be possible using the --tty parameter, but then I don't SSH into the server automatically anymore.

What's the recommended solution here?

Sake vs Ansible?

What are the key differences between Ansible and Sake? I can use Ansible to run tasks on different computers.

Distinguish servers by server-name, port and user in output

Is your feature request related to a problem? Please describe

When you access multiple hosts with the same hostname but different ports (e.g. running multiple virtualized servers on one host) you can't distinguish one from each other in the output.

config-example:

servers:
  VM1:
    host: root@server:22001
  VM2:
    host: user@server:22002
  VM3:
    host: root@server:22003

Running a task like an os-prober will create:

 host               | OS                                           
--------------------+----------------------------------------------
 server             | Debian 11                                    
 server             | Debian 10                                    
 server             | Debian 11                                    

The information about the different servernames, ports etc. is missing

Describe the solution you'd like

The output should (optionally) contain information about the server-name (VM1, VM2, VM3 in the example above) and / or port and username.

Additional context

./.

Improve Servers

This is an issue to improve the server object. I've gathered the following use-cases:

  • allow duplicate hosts #25
  • resolve hostnames from ssh_config #12
  • Support Bastion/Jumphost #32
  • Support shorthand user@ip:port
  • Support lowercase keys in ssh config
  • Resolve identity/identitiesonly in ssh config
  • Define multiple hosts without creating individual servers
  • Dynamically fetch hosts (via kubectl, reading from a text file or any other way)
  • Filtering
    • Regex filtering of servers
    • Pattern [0], [-1], [0:2], [:3]
    • Exclude/inverse option
    • Limit to x number of servers or percentage

Notes

  • How to target inventory? (%, number of servers, regex?)

Some initial mockup of the new design:

  • Expand env variables in inventory
  • Inventory example: for i in $(seq 1 100); do echo www.$i.example.com; done
    # sake run -s server-1 --number 1 # --number 25%
    servers:
      # One of the following:
      # host: 192.168.1.1
      # hosts: www[01:50].example.com # look at https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html#adding-ranges-of-hosts
      # hosts:
      # - 192.168.1.1
      # - 192.168.1.2
      inventory: kubectl get nodes # or cat hosts.txt # add example for k8s

How can a task pass a value to next task

Hi there,

I am testing the tool, I like the simplicity very useful. Thank you.

I want to know if there is a way to store output from a task to use in the next task in the same recipe?

Hope you can help me.

Regards,
Julio

Exec command with single quotes

Hi:

Maybe I'm not doing it right, but I don't know how to run a command with single quote in it.
When I run, for example:
sake exec -s server 'uname -r|awk -v FS='-' '{print $1}''

it fails with "Process exited with status 1".
I've tried with doble quote and "\", but I can't find a way for it to work

Is there a way to do it?

Best regards

Ansible

Hello.

Thanks for the projet, it is great.
But I wondering what are the differences from Ansible which seems to do the same job ?
Why did you create this tool ?

Thanks

Option to disable "Running" output

Is your feature request related to a problem? Please describe

Similar to alajmo/mani project, output from sake includes a Running spinner, which is also present when directed to file.

Describe the solution you'd like

Add an option to disable the Running spinner (-s, --silent).

Additional context

I use and enjoy both projects ;)

Bug ssh: handshake failed: ssh: unable to authenticate

  • I have the latest version of sake
  • I have searched through the existing issues

Info

  • OS

    • Linux
    • Mac OS X
    • Windows
    • other
  • Shell

    • Bash
    • Zsh
    • Fish
    • Powershell
    • other
  • Version: 0.15.1

Problem / Steps to reproduce

I have 1password as http agent and I've also tried with identity_file setting. Connecting to ssh doesnt work, and give me the following error:

ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey], no supported methods remain

I run: sake run ping

Receiving errors when attempting to use key files

Is your feature request related to a problem? Please describe.
I wasn't sure if this was the same problem as #5 so I'm opening a new issue just in case. I'm using a mac and whenever I try to run even a basic command like sake run ping --all using an identity key file I get one of two errors:

  1. error: failed to parse /Users/timothybryant/.ssh/id_ed25519_personal
    ssh: key is not password protected

so I created a new key file with a passphrase and now I get:

  1. error: failed to parse /Users/timothybryant/.ssh/id_rsa_password_protected
    bcrypt_pbkdf: empty password

I also tried using the -i command line argument instead but got the same results.

Describe the solution you'd like
I'm trying to run remote commands on VM's I have and I had hoped sake would be able to do that by ssh'ing to the hosts using the key files I have stored.

Additional context
Most of what I've done thus far (e.g. tasks, specs, etc) has come from the repo examples. Here is an example config for one of my VM's though:

servers:
  localhost:
    desc: localhost
    host: localhost
    local: true
    #work_dir: /tmp
    tags: [local]
  vm303:
    host: 192.168.1.74
    user: jsmith
    port: 22
    identity_file: ~/.ssh/id_ed25519_personal
    local: false
    tags: [cluster]

Be aware of `~/.ssh/config`

I was trying to configure a server in sake.yaml, by simply using the hostname as it is written in my ~/.ssh/config, but realized this does not work.

Example sake.yaml:

servers:
  myserver:
    host: myserver

Example ~/.ssh/config:

Host myserver
  Hostname 123.123.123.123
  User root

Can this be made to work?

Bug when using sake with .ssh/config

  • I have the latest version of sake
  • I have searched through the existing issues

Info

  • OS
    • Linux
  • Version: 0.15.0

  • Authentication:

    • Identity Key
  • Key Type:

    • ed25519
  • Key Format:

    • rfc4716

Problem / Steps to reproduce

sake.yaml:

servers:
  myserver:
    host: server

tasks:
  ping:
    desc: Pong
    cmd: echo "pong"

~/.ssh/config:

Host server
  HostName 123.123.123.123
  User root
  IdentityFile ~/.ssh/ailab_ed25519

sake run ping --all

Output:

error: open ~/.ssh/ailab_ed25519: no such file or directory
sake ssh myserver

Output:

[email protected]'s password:

It picks up my PC name (ronny) instead of the the server username (root).


$ ssh-keygen -t ed25519 -C "ailab-server"
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/ronny/.ssh/id_ed25519): ailab_ed25519
Enter passphrase (empty for no passphrase):
Enter same passphrase again:

Passphrase is empty

ipv6

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is.

When entering a ipv6 address i get the following error:
dial tcp: address fd58:9374:59b8:430c:8299:936b:7f1:49c:22: too many colons in address
If I put square brackets around i get:
error: cannot unmarshal !!seq into string

Describe the solution you'd like
A clear and concise description of what you want to happen.

I would like to be able to connect to servers using ipv6

Additional context
Add any other context or screenshots about the feature request here.

Workdir for remote is being used by `local: true` task

  • I have the latest version of sake
  • I have searched through the existing issues

Info

  • OS

    • Linux
    • Mac OS X
    • Windows
    • other
  • Shell

    • Bash
    • Zsh
    • Fish
    • Powershell
    • other

Installed with go install github.com/alajmo/sake@latest

  • Version:
Version: dev
Commit: none
Date: n/a

Problem / Steps to reproduce

sake.yml:

servers:
  localhost:
    host: 0.0.0.0
    local: true
  remote:
    host: 0.0.0.0
    local: true
    work_dir: does_not_exist

tasks:
  ping:
    desc: Pong
    target: {servers: [remote]}
    tasks:
      - cmd: echo "pong"
        local: true

What's wrong:

$ sake run ping

TASK*********

$ sake run --any-errors-fatal ping

TASK*********

error: chdir /tmp/t/does_not_exist: no such file or directory
  1. Task silently fails in case of sake run ping, though it did nothing. I expected sake to print any errors and logs happened during execution of task.
  2. work_dir is used for remote server and task is required to run locally (local: true). But sake tries to go into work_dir locally before executing task, which is wrong behavior.

Can't access libvirt hosts via dns name

  • I have the latest version of sake
  • I have searched through the existing issues

Info

  • OS

    • Linux
  • Shell

    • Zsh
  • Version:
    Version: 0.12.1
    Commit: ada7097
    Date: 2022-10-16T06:28:36Z

Problem / Steps to reproduce

I have some VMs running under libvirt, which are normally accessible via their host name, but sake can't resolve them. Resolution does work in other tools (ping, pyinfra, ansible, ssh, etc) so I don't think it's a general configuration error.

servers:
  localhost:
    host: 0.0.0.0
    local: true
  vm:
    host: host1vm

tasks:
  ping:
    desc: Pong
    cmd: echo "pong"
λ sake run ping --all


 Unreachable Hosts

 server | host    | user | port | error
--------+---------+------+------+---------------------------------------------------------------
 vm     | host1vm | soup | 22   | dial tcp: lookup host1vm on 127.0.0.53:53: server misbehaving

λ ping host1vm
PING host1vm (192.168.122.244) 56(84) bytes of data.
64 bytes from 192.168.122.244 (192.168.122.244): icmp_seq=1 ttl=64 time=0.141 ms
^C64 bytes from 192.168.122.244: icmp_seq=2 ttl=64 time=0.132 ms

You can use https://github.com/rktjmp/virt-up to bring up named hosts, but it does require some setup.

Same host different port

Hello

I've been playing with sake which is really good but I encountered a case where I have few servers on the same IP but with several SSH ports.

And sake throws an error

$ sake check
Found configuration errors:

error: found duplicate host `X.X.X.X` for the following servers

which is inconvenient because SSH supports it

Windows support

Would love to see Windows support added to this, both for client and for server side.

Support for .pem keys

Is your feature request related to a problem? Please describe.
Trying to use a private key with .pem extension gives the following error:

error: failed to parse `path/to/key.pem`
  ssh: not an encrypted key

Describe the solution you'd like
To be able to define servers that use .pem private key files

launching different comands on different servers

I want to stop system on several servers. I have two types of servers insert and storages.
on servers with tag insert i need to run command systemctl stop vm-insert and on storages systemctl stop vm-storage
i've made such config

tasks:
  stop-vm-insert:
    cmd: |
      echo "systemctl stop vm-insert";
      .... 
    target:
      tags: [insert]
  stop-vm-storage:
    cmd: |
      echo "systemctl stop vm-storage";
      ....
    target:
      tags: [ storage ]
  stop-daemons:
    tasks:
      - task: stop-vm-insert
      - task: stop-vm-storage

i'm expecting that commands must be issued only on target servers but instead they are run on both target groups.

Any ideas on how to do so ?

ssh: handshake failed

sake ssh remote-server
works as expected

sake exec 'ls' -s remote-server
for the same server returns an error: "ssh: handshake failed: ssh: unable to authenticate, attempted methods [none], no supported methods remain"

A remote command with plain ssh works:
ssh user@remote-server "ls"

Any hint why the connection fails if I try to execute a cmd via sake?

Too many authentication failures when defining lots of servers

  • I have the latest version of sake
  • I have searched through the existing issues

Info

  • OS

    • Linux
    • Mac OS X
    • Windows
    • other
  • Shell

    • Bash
    • Zsh
    • Fish
    • Powershell
    • other
  • Version: 0.10.1

Problem / Steps to reproduce

  1. Define lots of servers with different pubkey
  2. Attempt any task
  3. Some servers will fail as ALL pubkeys are tried one by one, which may exceed MaxAuthTries on sshd
ssh: handshake failed: ssh: disconnect, reason 2: Too many authentication failures

Observation

From the code here, all provided identities are collected and tried for each server with pubkey support.

sake/core/run/exec.go

Lines 163 to 166 in 47cdac6

// Iterate through servers and create a singleton AuthMethod, which is used for
// connecting to all hosts using a identity key. Servers which only use a password
// are not included here and are handled separately.
var identities []Identity

This should not be the case, each server should only try with (own) provided and global identity.

Also this approach is not very efficient as N servers with same pubkey will generate N identical identities. If a server using pubkey2 is declared below 100 servers using pubkey1, it will need to try 100 wrong identities before it can make connection, if even can pass the MaxAuthTries.

Allow multiple servers with the same host name

I want to use sake for managing parallel installations of software on my web hosting server; to so so, I would like to have different servers (with different usernames), but the same host as all of the accounts are sitting on the same server. Is this something you think would be meaningful?

Multiple bastions

Hi,
it just so happened that one of my server is only accessible through two bastions, so I think it'd be great to implement a solution for this in sake.

I've search for a phrase "bastion" in the repository and found this:
https://github.com/alajmo/sake/blob/main/core/run/unix.go#L31
If I'm not missing something then it seems like an pretty easy straightforward thing to do: put all bastions as a list in YAML file then echo each item of the list in this format: -J user@bastionA:port, user@bastionB:port.

What do you think about it?

error: strconv.ParseInt: parsing "": invalid syntax

  • I have the latest version of sake
  • I have searched through the existing issues

Info

  • OS

    • Linux
    • Mac OS X
    • Windows
    • other
  • Shell

    • Bash
    • Zsh
    • Fish
    • Powershell
    • other
  • Version: 0.10.3

Problem / Steps to reproduce

I get the following error message when running a command, no matter if I target a single server or all my servers:
error: strconv.ParseInt: parsing "": invalid syntax

sake check says that my configuration is OK.

This is my definition file:

servers:
    production:
        host: my.server.de
        port: 123
        user: user1
        local: false
        tags:
            - remote
    stage:
        host: my.server.de
        port: 123
        user: user2
        local: false
        tags:
            - remote
    test:
        host: my.server.de
        port: 123
        user: user3
        local: false
        tags:
            - remote
    internal:
        host: 192.1.2.3
        user: user
        local: false
        tags:
            - internal

tasks:
    ping:
        desc: Ping server
        cmd: ping $SAKE_SERVER_HOST
        local: true
    pwd:
        desc: Print working directory
        cmd: pwd

And this is what I'm running:
sake run ping --all

Outdated docs and NPE when formatting table headers

  • I have the latest version of sake
  • I have searched through the existing issues

Info

  • OS

    • Linux
    • Mac OS X
    • Windows
    • other
  • Shell

    • Bash
    • Zsh
    • Fish
    • Powershell
    • other
  • Version: 0.12.1

Problem / Steps to reproduce

Seems the config reference doc is not updated. I ran into problem configuring header format in newer version.

https://github.com/alajmo/sake/blob/main/docs/config-reference.md?plain=1#L117

~ sake.yaml (old) ~
specs:
  default:
    output: table
themes:
  default:
    table:
      format:
        header: upper

~ sake.yaml (new) ~
specs:
  default:
    output: table
themes:
  default:
    table:
      header:
        format: upper
$ sake check           ## runs fine
$ sake list servers    ## error
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x657177]

goroutine 1 [running]:
github.com/alajmo/sake/core/print.CreateTable({{0x0, 0x0}, {0x7d28f6, 0x5}, {{0xc0000ada90, 0x7}, {{0x0, 0x0}, {0x7d2761, 0x5}, ...}, ...}, ...}, ...)
        /home/runner/work/sake/sake/core/print/table.go:31 +0x197
github.com/alajmo/sake/core/print.table1[...]({_, _, _}, {{0x0, 0x0}, {0x7d28f6, 0x5}, {{0xc0000ada90, 0x7}, {{0x0, ...}, ...}, ...}, ...}, ...)
        /home/runner/work/sake/sake/core/print/print_table.go:48 +0x88
github.com/alajmo/sake/core/print.PrintTable[...]({_, _, _}, {{0x0, 0x0}, {0x7d28f6, 0x5}, {{0xc0000ada90, 0x7}, {{0x0, ...}, ...}, ...}, ...}, ...)
        /home/runner/work/sake/sake/core/print/print_table.go:33 +0x19e
github.com/alajmo/sake/cmd.listServers(0xae2340, {0xb1bb18?, 0x0?, 0x0?}, 0xc0000d2fa0, 0xc000080780)
        /home/runner/work/sake/sake/cmd/list_servers.go:121 +0x5e9
github.com/alajmo/sake/cmd.listServersCmd.func1(0xc00015cc80?, {0xb1bb18?, 0x0?, 0x0?})
        /home/runner/work/sake/sake/cmd/list_servers.go:33 +0x88
github.com/spf13/cobra.(*Command).execute(0xc00015cc80, {0xb1bb18, 0x0, 0x0})
        /home/runner/go/pkg/mod/github.com/spf13/[email protected]/command.go:876 +0x67b
github.com/spf13/cobra.(*Command).ExecuteC(0xadd680)
        /home/runner/go/pkg/mod/github.com/spf13/[email protected]/command.go:990 +0x3b4
github.com/spf13/cobra.(*Command).Execute(...)
        /home/runner/go/pkg/mod/github.com/spf13/[email protected]/command.go:918
github.com/alajmo/sake/cmd.Execute()
        /home/runner/work/sake/sake/cmd/root.go:42 +0x25
main.main()
        /home/runner/work/sake/sake/main.go:8 +0x17

Allow for full range of SSH port numbers

Currently only SSH port numbers up to 255 are supported. But many servers are configured by disabling connections on the default SSH port (22) and using a non well known port (such as 2200) instead.

This is because port is currently defined as a uint8. A change in data type to uint16 should fix this and allow for the full range of port numbers to be used.

This is the error message received when using a large port number:
image

Config file:

servers:
  server:
    host: 192.168.1.7
    port: 2222
  
tasks:
  ping:
    desc: Pong
    cmd: echo "pong"

Configuration handling

I have a simple question about one of the code decisions in this project. I see you've chosen to not use the golang viper library for handling configuration and have a custom implementation with yaml library. I was wondering if there was a specific reason for this decision? Viper is compatible with cobra, written by the same author, so it would've been a good option?

Port out of range error when used in host string

  • I have the latest version of sake
  • I have searched through the existing issues

Info

  • OS

    • Linux
    • Mac OS X
    • Windows
    • other
  • Shell

    • Bash
    • Zsh
    • Fish
    • Powershell
    • other
  • Version: 0.12.0

Problem / Steps to reproduce

~ sake.yaml ~
servers:
  myserver1:  ## not working (error: strconv.ParseInt: parsing "55555": value out of range)
    host: [email protected]:55555
  myserver2:  ## working
    host: [email protected]
    port: 55555
sake check

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.